Jump to content
Tuts 4 You

[DevirtualizeMe] Themida 3.0.3.0


DefCon42

Recommended Posts

Language : C++
Platform : Windows
OS Version : Windows 10
Packer / Protector : Themida 3.0.3.0

Description :

Looks like Oreans just dropped Themida 3. They've been working on the beta version for more than a year and just announced the initial release, so I'm praying I don't get my personal license revoked :^(

Strings are (supposedly) virtualized then encrypted. The main protection is starting at VM_DOLPHIN_RED, though other VMs can be requested.

Unpack/devirtualize the file.

Screenshot : 

image.png.95e3e0becbde54b73cb09b02c579cd0c.png

image.png.6a22f17b7cabd653464fc9ec2404c9b1.png

 

Themida Crackme_protected.exe

Link to comment
Share on other sites

  • 3 weeks later...

Answer

The password is "gamer vision".

All of the following addresses are based on the modulebase 0x00007FF644840000.

The possible OEP at:

00007FF644841DF8 | 48:895C24 20               | mov     qword ptr [rsp+20],rbx
00007FF644841DFD | 55                         | push    rbp
00007FF644841DFE | 48:8BEC                    | mov     rbp,rsp
00007FF644841E01 | 48:83EC 20                 | sub     rsp,20
...

Then the second hit in code section at:

00007FF6448416FC | 48:895C24 08               | mov     qword ptr [rsp+8],rbx
00007FF644841701 | 48:897424 10               | mov     qword ptr [rsp+10],rsi
00007FF644841706 | 57                         | push    rdi
00007FF644841707 | 48:83EC 30                 | sub     rsp,30
...

After prompted "enter password.", the input routine at:

00007FF644841400 | 48:8BC4                    | mov     rax,rsp
00007FF644841403 | 57                         | push    rdi
00007FF644841404 | 41:54                      | push    r12
00007FF644841406 | 41:55                      | push    r13
00007FF644841408 | 41:56                      | push    r14
00007FF64484140A | 41:57                      | push    r15
00007FF64484140C | 48:83EC 50                 | sub     rsp,50
...

the pointer of local buffer for receiving input text is in rdx(for example, 000000359CC9FA58).
When entered some test characters, stack looks like:

000000359CC9FA58:  31 32 33 34 35 36 37 38 39 30 31 32 00 7F 00 00              "123456789012"
000000359CC9FA68:  000000000000000C     input size
000000359CC9FA70:  000000000000000F     buffer size

Whereafter, the process logic virtualized.

First of all, the length of input text got checked in a vCmpqr handler:

00007FF644898E0B | 49:39F0                    | cmp     r8,rsi                  ; r8=000000000000000C(actual), rsi=000000000000000C(const)

The length MUST be 12!, else got "no!".
NOTE: the encrypt password has no chance to get decrypted if input length is wrong!

The answer String is encrypted(0xC length):

00007FF64484BCB0  8B 75 81 89 86 34 9A 8D 87 8D 83 82 00 00 00 00
decrypt algo:
00007FF6448BF3A6 | 40:8A36                    | mov     sil,byte ptr [rsi]                      rsi=00007FF64484BCB0, sil=8B
00007FF6448D4125 | 44:30DB                    | xor     bl,r11b                                 bl=8B, r11b=08; ^=08 = 83
00007FF64488E987 | 880A                       | mov     byte ptr [rdx],cl                       [00007FF64484BCB0] <- 83
00007FF64485748F | 8A09                       | mov     cl,byte ptr [rcx]                       [00007FF64484BCB0] -> 83
00007FF64485E6FA | 44:00D7                    | add     dil,r10b                                dil=83, r10b=E4; +=E4 = 67 'g'
00007FF64488E987 | 880A                       | mov     byte ptr [rdx],cl                       [00007FF64484BCB0] <- 67
00007FF64488DA96 | 49:FFC4                    | inc     r12                                     ptr++
00007FF644859691 | 41:FFC9                    | dec     r9d                                     length--
00007FF64488743C | 85C8                       | test    eax,ecx                                 end loop if length zero

At the end of loop, the plaintext:

00007FF64484BCB0  67 61 6D 65 72 20 76 69 73 69 6F 6E 00 00 00 00  gamer vision....

The comparison:

00007FF6448424E7 | FF25 330C0000              | jmp     qword ptr [<&memcmp>]                   ret rax=00000000FFFFFFFF/0000000000000000(if matches)
        rcx=000000359CC9FA58    "123456789012"
        rdx=00007FF64484BCB0    "gamer vision"
        r8=000000000000000C

 

Strings Encrypted

Structure

BYTE  bEncrypt          // 1 - encrypt, 0 - decrypt
DWORD dwLength
BYTE  UnDefined[0xC]
BYTE  CipherText[dwLength+1]

The related messages as followings, you can find them in the VM Section ".themida" after it got unpacked at the very beginning of the application.

00007FF6448AC79F  01 10 00 00 00 01 00 00 00 80 21 00 40 01 00 00               decrypt algo: ^A0+4F
00007FF6448AC7AF  00 B6 BF 85 B6 83 71 81 B2 84 84 88 80 83 B5 7F               "enter password.\n"
00007FF6448AC7BF  1B 00

00007FF64484BC9F  01 0C 00 00 00 72 64 2E 0A 00 00 00 00 00 00 00               decrypt algo: ^08+E4
00007FF64484BCAF  00 8B 75 81 89 86 34 9A 8D 87 8D 83 82 00                     "gamer vision"

00007FF644886C7F  01 05 00 00 00 72 20 76 69 73 69 6F 6E 00 00 00               decrypt algo: ^85+10
00007FF644886C8F  00 EC D0 E6 94 7F 00                                          "yes!\n"

00007FF64489252F  01 04 00 00 00 00 00 00 00 79 65 73 21 0A 00 00               decrypt algo: ^65+C9
00007FF64489253F  00 C0 C3 3D 24 00                                             "no!\n"

00007FF64484C40F  01 19 00 00 00 0A 00 00 00 6E 6F 21 0A 00 00 00               decrypt algo: ^12+C6
00007FF64484C41F  00 B8 BE 8D BF BF 48 8D BA BC 8D BE 48 BC BB 48               "press enter to continue.\n"
00007FF64484C42F  8F BB BA BC B1 BA BD 8D 7A 56 00

 

  • Like 11
  • Thanks 4
Link to comment
Share on other sites

On 7/10/2019 at 10:29 AM, MistHill said:

Answer

The password is "gamer vision".

All of the following addresses are based on the modulebase 0x00007FF644840000.

The possible OEP at:


00007FF644841DF8 | 48:895C24 20               | mov     qword ptr [rsp+20],rbx
00007FF644841DFD | 55                         | push    rbp
00007FF644841DFE | 48:8BEC                    | mov     rbp,rsp
00007FF644841E01 | 48:83EC 20                 | sub     rsp,20
...

Then the second hit in code section at:


00007FF6448416FC | 48:895C24 08               | mov     qword ptr [rsp+8],rbx
00007FF644841701 | 48:897424 10               | mov     qword ptr [rsp+10],rsi
00007FF644841706 | 57                         | push    rdi
00007FF644841707 | 48:83EC 30                 | sub     rsp,30
...

After prompted "enter password.", the input routine at:


00007FF644841400 | 48:8BC4                    | mov     rax,rsp
00007FF644841403 | 57                         | push    rdi
00007FF644841404 | 41:54                      | push    r12
00007FF644841406 | 41:55                      | push    r13
00007FF644841408 | 41:56                      | push    r14
00007FF64484140A | 41:57                      | push    r15
00007FF64484140C | 48:83EC 50                 | sub     rsp,50
...

the pointer of local buffer for receiving input text is in rdx(for example, 000000359CC9FA58).
When entered some test characters, stack looks like:


000000359CC9FA58:  31 32 33 34 35 36 37 38 39 30 31 32 00 7F 00 00              "123456789012"
000000359CC9FA68:  000000000000000C     input size
000000359CC9FA70:  000000000000000F     buffer size

Whereafter, the process logic virtualized.

First of all, the length of input text got checked in a vCmpqr handler:


00007FF644898E0B | 49:39F0                    | cmp     r8,rsi                  ; r8=000000000000000C(actual), rsi=000000000000000C(const)

The length MUST be 12!, else got "no!".
NOTE: the encrypt password has no chance to get decrypted if input length is wrong!

The answer String is encrypted(0xC length):


00007FF64484BCB0  8B 75 81 89 86 34 9A 8D 87 8D 83 82 00 00 00 00
decrypt algo:
00007FF6448BF3A6 | 40:8A36                    | mov     sil,byte ptr [rsi]                      rsi=00007FF64484BCB0, sil=8B
00007FF6448D4125 | 44:30DB                    | xor     bl,r11b                                 bl=8B, r11b=08; ^=08 = 83
00007FF64488E987 | 880A                       | mov     byte ptr [rdx],cl                       [00007FF64484BCB0] <- 83
00007FF64485748F | 8A09                       | mov     cl,byte ptr [rcx]                       [00007FF64484BCB0] -> 83
00007FF64485E6FA | 44:00D7                    | add     dil,r10b                                dil=83, r10b=E4; +=E4 = 67 'g'
00007FF64488E987 | 880A                       | mov     byte ptr [rdx],cl                       [00007FF64484BCB0] <- 67
00007FF64488DA96 | 49:FFC4                    | inc     r12                                     ptr++
00007FF644859691 | 41:FFC9                    | dec     r9d                                     length--
00007FF64488743C | 85C8                       | test    eax,ecx                                 end loop if length zero

At the end of loop, the plaintext:


00007FF64484BCB0  67 61 6D 65 72 20 76 69 73 69 6F 6E 00 00 00 00  gamer vision....

The comparison:


00007FF6448424E7 | FF25 330C0000              | jmp     qword ptr [<&memcmp>]                   ret rax=00000000FFFFFFFF/0000000000000000(if matches)
        rcx=000000359CC9FA58    "123456789012"
        rdx=00007FF64484BCB0    "gamer vision"
        r8=000000000000000C

 

Strings Encrypted

Structure


BYTE  bEncrypt          // 1 - encrypt, 0 - decrypt
DWORD dwLength
BYTE  UnDefined[0xC]
BYTE  CipherText[dwLength+1]

The related messages as followings, you can find them in the VM Section ".themida" after it got unpacked at the very beginning of the application.


00007FF6448AC79F  01 10 00 00 00 01 00 00 00 80 21 00 40 01 00 00               decrypt algo: ^A0+4F
00007FF6448AC7AF  00 B6 BF 85 B6 83 71 81 B2 84 84 88 80 83 B5 7F               "enter password.\n"
00007FF6448AC7BF  1B 00

00007FF64484BC9F  01 0C 00 00 00 72 64 2E 0A 00 00 00 00 00 00 00               decrypt algo: ^08+E4
00007FF64484BCAF  00 8B 75 81 89 86 34 9A 8D 87 8D 83 82 00                     "gamer vision"

00007FF644886C7F  01 05 00 00 00 72 20 76 69 73 69 6F 6E 00 00 00               decrypt algo: ^85+10
00007FF644886C8F  00 EC D0 E6 94 7F 00                                          "yes!\n"

00007FF64489252F  01 04 00 00 00 00 00 00 00 79 65 73 21 0A 00 00               decrypt algo: ^65+C9
00007FF64489253F  00 C0 C3 3D 24 00                                             "no!\n"

00007FF64484C40F  01 19 00 00 00 0A 00 00 00 6E 6F 21 0A 00 00 00               decrypt algo: ^12+C6
00007FF64484C41F  00 B8 BE 8D BF BF 48 8D BA BC 8D BE 48 BC BB 48               "press enter to continue.\n"
00007FF64484C42F  8F BB BA BC B1 BA BD 8D 7A 56 00

 

Impressive! Should I upload a different VM as well if you want to take a shot at it?

Link to comment
Share on other sites

On ‎7‎/‎12‎/‎2019 at 8:50 AM, DefCon42 said:

Impressive! Should I upload a different VM as well if you want to take a shot at it?

No, thanks.

Compared to Themida v2, the themida v3 does not have a great improvement over the VMs.
There are two types of VMs in this UnPackMe, Dolphin and Tiger.

  • Like 3
Link to comment
Share on other sites

  • 2 years later...

I have made my tool works on x64 in my spare time so tried  this challenge.

  • Unpacking

concerning this challenge ,OEP is virtualized and IAT is obfuscated. obfuscation scheme has been changed totally since 3.x.

  • Devirtualization

decryption algorithm were already posted.
I analyzed almost code obfuscated from start to end  and recovered code flow while keeping original code. but might have overlooked trivial part. code flow(pseudo code) is as follows.

char* yes,no,enter_password,gamer_vision,enter_continue,ans;
decrypt(entr_password);
print(enter_password);

std::widen('.');
std::cin>>buff;
ans = no;
if(buff.length() == 12)
{
  decrypt(gamer_vision);
  if(memcmp(buff,gamer_vision) == 0){
  		ans = yes; 
  }
}

decrypt(no);
decrypt(yes);
print(ans);

decrypt(enter_continue);
print(enter_continue);
std::cin.ignore();
return 

Note that this code is written with focus on virtualized part.

 attached unpacked & devirtualized binary.

 

Unpacked.exe

  • Like 4
Link to comment
Share on other sites

  • 2 weeks later...
Sean Park - Lovejoy

2 wonderful reversers from china nad japan. good for you.

thank you for your posts.

regards.

sean.

Link to comment
Share on other sites

  • 1 year later...
raulinonogues
On 21/06/2019 at 10:49, DefCon42 said:

Idioma:
Plataforma C++ :
Versão do sistema operacional Windows : Windows 10
Packer/Protetor: Themida 3.0.3.0

Descrição :

Parece que os oreanos acabaram de lançar o Themida 3. Eles estão trabalhando na versão beta há mais de um ano e acabaram de anunciar o lançamento inicial, então estou rezando para que minha licença pessoal não seja revogada :^(

As strings são (supostamente) virtualizadas e depois criptografadas. A proteção principal começa em VM_DOLPHIN_RED, embora outras VMs possam ser solicitadas.

Descompacte/desvirtualize o arquivo.

Captura de tela : 

image.png.95e3e0becbde54b73cb09b02c579cd0c.png

image.png.6a22f17b7cabd653464fc9ec2404c9b1.png

hello what is the password

Themida Crackme_protected.exe 2,93 MB · 410 downloads

 

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...