Scan of the month 33: (0x90.exe)
by Nicolas Brulez
at http://www.honeynet.org/scans/scan33/
Solution by E. Grandjean (e.grandjean at no-log.org)

Valid XHTML 1.1! Valid CSS!

Summary

The Challenge

"All we are going to tell you about the binary is that it was 'found' on a WinXP system and has now be sent to you for analysis. You will have to analyse it in-depth and get as much information as possible about its inner working, and what is the goal of the binary. The main goal of this challenge is to teach people how to analyse heavily armored binaries."


My english is very poor... I hope you can understand me.
I used Ollydbg to study the binary, and I didn't write any own tool to help me to progress in the code.
I traced all the code, but we will see there are a lot of vulnerabilities in the protection and we will be able to progress quickly.

1. Identify and explain any techniques in the binary that protect it from being analyzed or reverse engineered.

If we try to disassemble the binary with IDA (Interactive Disassembler Pro), an error occurs. In fact it is due to the raw size of the third section.

   3. item:
    Name:                  NicolasB	( <------ a little note on the name of the section :
		                                  it is not a "classical" name of sections. 
		                                  The name has been chosen by Nicolas Brulez.
		                                  The name of a section can be changed, there 
		                                  is only one condition : the maximum size 
		                                  is 8 characters. )
    VirtualSize:           0x00001000
    VirtualAddress:        0x00047000
    SizeOfRawData:         0xEFEFADFF   <---- This size is too large and IDA can't allocate memory.
    PointerToRawData:      0x00047000
    PointerToRelocations:  0x00000000
    PointerToLinenumbers:  0x00000000
    NumberOfRelocations:   0x0000
    NumberOfLinenumbers:   0x0000
    Characteristics:       0xE00000E0
    (CODE, INITIALIZED_DATA, UNINITIALIZED_DATA, EXECUTE, READ, WRITE)

Normally SizeOfRawData contains the size of the section after VirtualSize has been rounded up to the file alignment size (0x200h for example).

That will not be a problem for us, Ollydbg is able to disassemble the binary although this trick is present. But the debugger can't break at the EP (the entrypoint of the program) when we load it. If we want to force the breakpoint, we need to physically modificate the code : a PE editor tells us the offset of the entrypoint is 0x00002000. We load the binary in an editor hexadecimal,

00002000  60 E8 00 00 00 00 5D 8B C5 83 E8 06 81 ED 06 20

and we replace the first byte at the entrypoint (0x60) by 0xCC (the opcode of the int3 breakpoint).

00DE2000    CC              INT3                 ; 0xCC instead of 0x60
00DE2001    E8 00000000     CALL 0x90.00DE2006
00DE2006    5D              POP EBP

Now the binary will break at the EP under ollydbg, but we need to restore this byte with the original byte before beginning to trace the loader.

00DE2000    60              PUSHAD               ; byte restored
00DE2001    E8 00000000     CALL 0x90.00DE2006
00DE2006    5D              POP EBP

All along we will meet obfuscation code and code redirected, what will make the static analysis impossible, unless we write a script that will clean the code. But as I said before, I traced all the code so it didn't disturb me anymore.

An example :

00DE2012    60              PUSHAD
00DE2013    8AC3            MOV AL,BL
00DE2015    65:             PREFIX GS:				; junk code
00DE2016    36:F3:          PREFIX REP:				; junk code
00DE2018    8BCA            MOV ECX,EDX
00DE201A    F2:             PREFIX REPNE:			; junk code
00DE201B    EB 01           JMP SHORT 0x90.00DE201E		; junk code
00DE201D    AB              STOS DWORD PTR ES:[EDI]		; not executed
00DE201E    89F6            MOV ESI,ESI				; utility ?
00DE2020    26:F2:          PREFIX REPNE:			; junk code
00DE2022    8D1D 6E7CE4D0   LEA EBX,DWORD PTR DS:[D0E47C6E]
00DE2028    65:             PREFIX GS:				; junk code
00DE2029    F2:64:          PREFIX REPNE:			; junk code
00DE202B    C6C4 51         MOV AH,51
00DE202E    EB 01           JMP SHORT 0x90.00DE2031
00DE2030    27              DAA					; not executed
00DE2031    2E:8AC5         MOV AL,CH
00DE2034    F3:65:          PREFIX REP:				; junk code
00DE2036    EB 01           JMP SHORT 0x90.00DE2039
00DE2038    14 EB           ADC AL,0EB				; the first byte needs to be nopped

So, after the nop :

00DE2036   /EB 01           JMP SHORT 0x90.00DE2039		; utility ?
00DE2038   |90              NOP
00DE2039   \EB 01           JMP SHORT 0x90.00DE203C
00DE203B  ^ 76 8B           JBE SHORT 0x90.00DE1FC8		; the first byte needs to be nopped

After the nop :

00DE2039   \EB 01           JMP SHORT 0x90.00DE203C
00DE203B    90              NOP
00DE203C    8BF9            MOV EDI,ECX
00DE203E    B1 00           MOV CL,0
00DE2040    64:C6C0 0D      MOV AL,0D
00DE2044    88C9            MOV CL,CL				; utility ?
00DE2046    26:             PREFIX ES:				; junk code
00DE2047    65:8D3D CA77656>LEA EDI,DWORD PTR GS:[686577CA]
00DE204E    64:F2:          PREFIX REPNE:			; junk code
00DE2050    8D3D 54804E35   LEA EDI,DWORD PTR DS:[354E8054]	; previous value of edi changed !
00DE2056    65:8AEE         MOV CH,DH
00DE2059    3E:             PREFIX DS:				; junk code
00DE205A    64:8BF8         MOV EDI,EAX
00DE205D    F2:26:          PREFIX REPNE:			; junk code
00DE205F    89DB            MOV EBX,EBX				; utility ?
00DE2061    EB 01           JMP SHORT 0x90.00DE2064
00DE2063    3C 65           CMP AL,65				; not executed
00DE2065    64:C6C7 B5      MOV BH,0B5				; the first byte needs to be nopped

To be continued...
It's very difficult to understand what happens :)
The value of the registers are continually modified, even if it is not necessary... and the reverse engineer gets mad !!

Concerning people who thought it would be possible to break to a judicious part of a code by finding the referenced data strings, they will be disappointed, and Nicolas Brulez thought to them ;) :

00E280DF  00 59 6F 75 20 72 65 61 6C 6C 79 20 74 68 6F 75  .You really thou
00E280EF  67 68 74 20 79 6F 75 20 77 6F 75 6C 64 20 66 69  ght you would fi
00E280FF  6E 64 20 73 74 72 69 6E 67 73 20 65 68 3F 20 3B  nd strings eh? ;
00E2810F  2D 29 00 00 00 00 00 00                          -)......

Another curiosity, maybe a signature ? :

00DE0100  50 45 00 00 4C 01 04 00 63 31 1C 85 44 61 72 74  PE..L...c1...Dart
00DE0110  68 50 45 00 E0 00 8F 81 0B 01 02 19 00 02 00 00  hPE.............

In 00DE0100, we can see the beginning of the IMAGE_NT_HEADERS ("50 45 00 00" (PE\00) is the signature of the PE File).
This is the structure of the IMAGE_NT_HEADERS :

IMAGE_NT_HEADERS STRUCT
    Signature dd ?
    FileHeader IMAGE_FILE_HEADER <>
    OptionalHeader IMAGE_OPTIONAL_HEADER32 <>
IMAGE_NT_HEADERS ENDS

So the following values correspond to the IMAGE_FILE_HEADER.
The structure of IMAGE_FILE_HEADER is :

IMAGE_FILE_HEADER STRUCT
    Machine WORD ?
    NumberOfSections WORD ?
    TimeDateStamp dd ?
    PointerToSymbolTable dd ?
    NumberOfSymbols dd ?
    SizeOfOptionalHeader WORD ?
    Characteristics WORD ?
IMAGE_FILE_HEADER ENDS

Machine = 4C 01 -> 0x14C : it is used for the Intel platform
NumberOfSections = 04 00 -> 4
TimeDateStamp = 63 31 1C 85 -> 851C3163 : give iformations about the date and time the file was created.
PointerToSymbolTable = 44 61 72 74 -> "Dart"
NumberOfSymbols = 68 50 45 00 -> "hPE "

PointerToSymbolTable and NumberOfSymbols are normally used for debugging. In this binary Nicolas Brulez seems to use it to put a signature or something like that : "DarthPE"

In the first part of the loader, anti-debugging tricks are :
- Clear Debug Registers (anti-BPM)
- Check the time after the execution of the binary (anti-tracing)

They are hidden in a SEH executed after an exception like this :

00DE2289    60              PUSHAD
00DE228A    E8 48000000     CALL 0x90.00DE22D7
00DE228F    8B4C24 0C       MOV ECX,DWORD PTR SS:[ESP+C]
00DE2293    8381 B8000000 0>ADD DWORD PTR DS:[ECX+B8],2
00DE229A    33C0            XOR EAX,EAX
00DE229C    8941 04         MOV DWORD PTR DS:[ECX+4],EAX
00DE229F    8941 08         MOV DWORD PTR DS:[ECX+8],EAX
00DE22A2    8941 0C         MOV DWORD PTR DS:[ECX+C],EAX
00DE22A5    8941 10         MOV DWORD PTR DS:[ECX+10],EAX
00DE22A8    8941 14         MOV DWORD PTR DS:[ECX+14],EAX
00DE22AB    C741 18 5501000>MOV DWORD PTR DS:[ECX+18],155
00DE22B2    8B81 B0000000   MOV EAX,DWORD PTR DS:[ECX+B0]
00DE22B8    50              PUSH EAX
00DE22B9    0FA2            CPUID
00DE22BB    0F31            RDTSC
00DE22BD    2B0424          SUB EAX,DWORD PTR SS:[ESP]
00DE22C0    83C4 04         ADD ESP,4
00DE22C3    3D 00000E00     CMP EAX,0E0000
00DE22C8    77 03           JA SHORT 0x90.00DE22CD
00DE22CA    33C0            XOR EAX,EAX
00DE22CC    C3              RETN
00DE22CD    8381 B8000000 6>ADD DWORD PTR DS:[ECX+B8],63
00DE22D4    33C0            XOR EAX,EAX
00DE22D6    C3              RETN
00DE22D7    33C0            XOR EAX,EAX				
00DE22D9    64:FF30         PUSH DWORD PTR FS:[EAX]  ; pointer to next SEH record
                                                     ; 00DE228F is the SEH handler (instruction
                                                     ; after the call
------------------------------------------------
In the stack we can see :
0012FF7C   0012FFE0  Pointer to next SEH record
0012FF80   00DE228F  SE handler
------------------------------------------------

00DE22DC    64:8920         MOV DWORD PTR FS:[EAX],ESP
00DE22DF    0FA2            CPUID
00DE22E1    0F31            RDTSC
00DE22E3    33DB            XOR EBX,EBX             ; ebx = 0					
00DE22E5    8F03            POP DWORD PTR DS:[EBX]  ; exception C0000005 (access violation)
                                                    ; -> the SEH handler is called
00DE22E7    64:67:8F06 0000 POP DWORD PTR FS:[0]    ; Out of the SEH
00DE22ED    83C4 04         ADD ESP,4               ; restore the stack
00DE22F0    61              POPAD

There are different forms for the SEHs in this binary :

Form 1 :

<---- Clear the Debug Register ---->
00E2534C    8B7C24 0C       MOV EDI,DWORD PTR SS:[ESP+C]	; edi = pointer to the context structure
00E25350    8387 B8000000 0>ADD DWORD PTR DS:[EDI+B8],2		; eip ([EDI+B8]) = eip + 2 to jmp to the 
                                                                ; next instruction
00E25357    33C0            XOR EAX,EAX				; eax = 0
00E25359    8D7F 04         LEA EDI,DWORD PTR DS:[EDI+4]	
00E2535C    AB              STOS DWORD PTR ES:[EDI]		;[edi+4] = DR0 = 0
00E2535D    AB              STOS DWORD PTR ES:[EDI]		;[edi+8] = DR1 = 0
00E2535E    AB              STOS DWORD PTR ES:[EDI]		;[edi+C] = DR2 = 0
00E2535F    AB              STOS DWORD PTR ES:[EDI]		;[edi+10] = DR3 = 0
00E25360    AB              STOS DWORD PTR ES:[EDI]		;[edi+14] = DR6 = 0
00E25361    66:B8 AA01      MOV AX,1AA
00E25365    34 FF           XOR AL,0FF				; ax = 155
00E25367    AB              STOS DWORD PTR ES:[EDI]		;[edi+18] = DR7 = 155
00E25368    8B87 A8000000   MOV EAX,DWORD PTR DS:[EDI+A8]	; eax = edx ([EDI+A8] context structure)
00E2536E    8140 28 32875A0>ADD DWORD PTR DS:[EAX+28],45A8732
00E25375    8B87 94000000   MOV EAX,DWORD PTR DS:[EDI+94]
00E2537B    50              PUSH EAX
<---- the equivalent of GetTickCount ---->
00E2537C    0FA2            CPUID			
00E2537E    0F31            RDTSC				; ReaD TimeStamp Counter
00E25380    2B0424          SUB EAX,DWORD PTR SS:[ESP]		; sub the last value of RDTSC	
00E25383    83C4 04         ADD ESP,4
00E25386    3D 00000E00     CMP EAX,0E0000			; cmp number of cycles cpu with 0x0E0000
00E2538B    77 10           JA SHORT 0x90.00E2539D		; if eax > 0x0E0000, process traced/debugged
00E2538D    8B87 A8000000   MOV EAX,DWORD PTR DS:[EDI+A8]	; else OK and eax = edx ([EDI+A8] context 
                                                                ; structure)
00E25393    8168 28 7FAB350>SUB DWORD PTR DS:[EAX+28],235AB7F
00E2539A    2BC0            SUB EAX,EAX
00E2539C    C3              RETN
<---- if process debugged/traced ---->
00E2539D    8387 9C000000 3>ADD DWORD PTR DS:[EDI+9C],32	; edi ([EDI+9C]) = edi + 0x32 ->
								; exception 0xC0000005 (access violation)
00E253A4    2BC0            SUB EAX,EAX				; and loop, the stack is full of SEH handlers
00E253A6    C3              RETN				; and ollydbg crashes.

Form 2 :

<---- Clear the Debug Register ---->
00DE865E    8B4C24 0C       MOV ECX,DWORD PTR SS:[ESP+C]	; ecx = pointer to the context structure
00DE8662    8381 B8000000 0>ADD DWORD PTR DS:[ECX+B8],2		; eip ([ECX+B8]) = eip + 2 to jmp to the 
                                                                ; next instruction
00DE8669    33C0            XOR EAX,EAX				; eax = 0
00DE866B    8941 04         MOV DWORD PTR DS:[ECX+4],EAX	;[ecx+4] = DR0 = 0
00DE866E    8941 08         MOV DWORD PTR DS:[ECX+8],EAX	;[ecx+8] = DR1 = 0
00DE8671    8941 0C         MOV DWORD PTR DS:[ECX+C],EAX	;[ecx+C] = DR2 = 0
00DE8674    8941 10         MOV DWORD PTR DS:[ECX+10],EAX	;[ecx+10] = DR3 = 0
00DE8677    8941 14         MOV DWORD PTR DS:[ECX+14],EAX	;[ecx+14] = DR6 = 0
00DE867A    C741 18 5501000>MOV DWORD PTR DS:[ECX+18],155	;[ecx+18] = DR7 = 155
00DE8681    8B81 B0000000   MOV EAX,DWORD PTR DS:[ECX+B0]	; eax = eax ([ECX+B0]) of the context 
                                                                ; structure
00DE8687    50              PUSH EAX
<---- the equivalent of GetTickCount ---->
00DE8688    0FA2            CPUID
00DE868A    0F31            RDTSC				; ReaD TimeStamp Counter
00DE868C    2B0424          SUB EAX,DWORD PTR SS:[ESP]		; sub the last value of RDTSC
00DE868F    83C4 04         ADD ESP,4
00DE8692    3D 00000E00     CMP EAX,0E0000			; cmp number of cycles cpu with 0x0E0000
00DE8697    77 03           JA SHORT 0x90.00DE869C		; if eax > 0x0E0000, process traced/debugged
00DE8699    33C0            XOR EAX,EAX				; else OK
00DE869B    C3              RETN
<---- if process debugged/traced ---->
00DE869C    8381 B8000000 6>ADD DWORD PTR DS:[ECX+B8],63	; eip ([ECX+B8]) = eip + 0x63 -> 
								; exception 0xC0000005 (access violation)
00DE86A3    33C0            XOR EAX,EAX				; and loop, the stack is full of SEH handlers
00DE86A5    C3              RETN				; and ollydbg crashes.

The Debug Registers are used for the hardware breakpoints.
There are :

To modify the Debug Registers you need to use the context structure (in theory they are only available in ring 0, but when an exception happens, we can access to the Context if we want). In fact the Context presents the state of all the registers at the moment of the exception.

This is a partial dump of the Context Structure :

# CONTEXT STRUCT
;-------------------------
; CONTEXT_DEBUG_REGISTERS
;-------------------------
+04 Dr0 dd ?
+08 Dr1 dd ?
+0C Dr2 dd ?
+10 Dr3 dd ?
+14 Dr6 dd ?
+18 Dr7 dd ?
;-------------------------
; CONTEXT_SEGMENTS
;-------------------------
+8C regGs dd ?
+90 regFs dd ?
+94 regEs dd ?
+98 regDs dd ?
;-------------------------
; CONTEXT_INTEGER
;-------------------------
+9C regEdi dd ?
+A0 regEsi dd ?
+A4 regEbx dd ?
+A8 regEdx dd ?
+AC regEcx dd ?
+B0 regEax dd ?
;-------------------------
; CONTEXT_CONTROL
;-------------------------
+B4 regEbp dd ?
+B8 regEip dd ?
+BC regCs dd ?
+C0 regFlag dd ?
+C4 regEsp dd ?
+C8 regSs dd ? 

The detection by timing uses RDTSC. This instruction set in eax (and edx) un number of cpu cycles. To mesure the number of cpu cycles passed, it is necessary to execute this instruction two times at minimum.
CPUID is an instruction of synchronisation. Used with RDTSC, it allows us to not have false positive and to execute the instructions in the right order.
If the detection by timing is efficient, we don't go out of the exception, we return in the SEH and the new SEH handler is set into the stack. It is an infinity loop, so if we are detected with RDTSC, the stack is full of SEH handler and Ollydbg crashes.

To break at the beginning of a new SEH, I set a hardware breakpoint on execution on the SEH Handler (readable on the stack).
In short all my BPMs were set on MOV ECX,DWORD PTR SS:[ESP+C] or on MOV EDI,DWORD PTR SS:[ESP+C], before the debug registers will be set to zero.
It is the only way to set BPM on execution during the study. If we set BPM in an other part than the SEH handler, it would be cleared.
JA = Jump if above. Jump if Carry Flag = 0 and Zero Flag = 0.
To continue tracing after a SEH in the part of the loader, I set the Zero Flag to 1 (the binary thinks the number of the cpu cycles are equal to 0x0E0000) before executing the "ja" and I set "break on access (execution)" on the item of the binary in the Memory Map (button M in ollydbg), that will make me return into the code of the loader.

Memory map, item 15
 Address=00DE0000
 Size=0004A000 (303104.)
 Owner=0x90 00DE0000 (itself)
 Section=
 Contains=PE header
 Type=Imag 01001102
 Access=R   Guarded
 Initial access=RWE

In the second part of the loader, there are a lot of encryption layers (more than 100... I was too lazy to count them). It is only a xor encryption (the value to xor with changes for each layer), but the registers used are always differents, that's why it is more difficult to write a script of decryption.
I passed them all manually...
I saw a detection of 0xCC (opcode of int3 breakpoint -> when we set a breakpoint (F2 with ollydbg) with the debugger, that modifies the code and set a 0xCC opcode instead of the original byte) at the beginning of the new code decrypted, but to pass the decryption of the layers more quickly, we can set a breakpoint after the loop if we want (there is not detection of 0xCC after the loop).

After each encryption layer, the debug registers are cleared and the time is checked as explained above.
Before the next layer decryption, the last layer crypts itself again : in this way the entire binary will never be completely decrypted in memory.

I detected a vulnerability in the code that allow us to go quickly enough :
When we arrive on a SEH, the next part of the code is already decrypted and there is no obfuscation, so we can read it a little bit above in the listing asm. So it is possible to progress in the layers only setting hardware breakpoint on execution on the next SEH Handler (when they are set at this part, they are never cleared).

We enter to the third part of the loader when we see :

00DE8CCC    C705 3687DE00 4>MOV DWORD PTR DS:[DE8736],6C697645  ;"Evil"
00DE8F79    C705 3A87DE00 2>MOV DWORD PTR DS:[DE873A],73614820  ;" Has"
00DE920E    C705 3E87DE00 2>MOV DWORD PTR DS:[DE873E],206F4E20	;" No "
00DE94AA    C705 4287DE00 4>MOV DWORD PTR DS:[DE8742],6E756F42	;"Boun"
00DE977C    C705 4687DE00 6>MOV DWORD PTR DS:[DE8746],69726164	;"dari"
00DE99E9    C705 4A87DE00 6>MOV DWORD PTR DS:[DE874A],21207365	;"es !"

The memory address [DE8736] will be very usefull, and a constant verification of the values stored here will be important.

2. Something uncommon has been used to protect the code from beeing reverse engineered, can you identificate what it is and how it works ?

This uncommon thing is a virtual machine (VM) wrote to protect the binary and make the assembly code harder to understand.
Nicolas Brulez wrote his own p-code instructions and his own registers, and the p-code is interpreted by the the VM. The opcodes are pushed on the stack and then executed.
We can see a repetitive loop to call the VM.

P-code is simply code interpreted during execution time, it could be thought as generic machine-level code that requires a previous translation to its native machine-code. It is the same to compiled java : in order to execute JAVA-written applications we need a translator placed between the JAVA-code and the code that our processor understands. The translator is the VM.
Nicolas Brulez defines a proprietary set of instructions and doesn't publish their significations, so we are going to have a hard time understanding the code.

The esi register is used to progress in the p-code. If we keep on tracing we see the access to the buffer pointed by esi is continuously repeated.
eax and ecx are used for store value before manipulations of the registers.
Memory addresses at [EAX*4+DE8736] is used to store values in memory.
Memory adress at [E1B991] seems to be the base address to the buffer that contained the opcodes to be interpreted.
Memory adress at [DE874A] is a mark : it is set to 1 to continue and 0 to quit the loop or the treatement.

After the encryption layers, there is an other decryption loop, a xor 0x53 decryption, that can be passed more quickly by setting hardware breakpoints at :

00E09A71
00E0E7D2
00DF9004
00E0B5A3

This loop will decrypt all the third part of the loader : the rest of the infamous virtual machine.

Code of the loop of decryption (only the important instructions of the Virtual Machine are quoted here) :

esi = 00E1BA44  00 01 2E A7

00DFE7A5    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 0	
00DFEA74    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90.00E1B9A9
00DFED0E    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 1
00DEC633    8B46 02         MOV EAX,DWORD PTR DS:[ESI+2]		; eax = 5311A72E
00DEC8CD    05 3713D0AD     ADD EAX,ADD01337				; eax = 00E1BA65
00DECB8A    50              PUSH EAX
00DECE37    B8 D1F5FFFF     MOV EAX,-0A2F				; eax = FFFFF5D1
00DED113    F7D0            NOT EAX					; eax = 00000A2E
00DED3BB    35 280A0000     XOR EAX,0A28				; eax = 00000006
00DED680    8D3406          LEA ESI,DWORD PTR DS:[ESI+EAX]		; [00E1BA44 + 6] => esi = 00E1BA4A
00DED936    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 0
00DEDC00    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90.00E1B9A9
00DEDE7F    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 3
00E1B372    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 0x66
00E1B376    83F0 66         XOR EAX,66					; eax = 0
00E1B64A    8F0485 3687DE00 POP DWORD PTR DS:[EAX*4+DE8736]         	; 0x90.00E1BA65

00DE8736  45 76 69 6C                                      Evil
00DE8736  65 BA E1 00                                      eºá.

00E1B8CF    83C6 04         ADD ESI,4					; esi = 00E1BA4E
00E1B8D2    4E              DEC ESI					; esi = 00E1BA4D

00E1BA4D  02 02 4F 13

00E1B8D3    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00E1B8D6    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]		; edi = 00E1B9F5
00E1B8DD    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 2
00DFDCAD    8B46 02         MOV EAX,DWORD PTR DS:[ESI+2]		; eax = 5102134F
00DFDF5E    05 04EDFDAE     ADD EAX,AEFDED04				; eax = 00000053
00DFE20E    0FB67E 06       MOVZX EDI,BYTE PTR DS:[ESI+6]		; edi = 2
00DFE4DC    8904BD 3687DE00 MOV DWORD PTR DS:[EDI*4+DE8736],EAX

00DE873E  20 4E 6F 20                                       No
00DE873E  53 00 00 00                                      S...

00DFE4E3    83C6 07         ADD ESI,7					; esi = 00E1BA54

00DE872E                          65 BA E1 00 20 48 61 73          eºá. Has
00DE873E  53 00 00 00 0E 02 00 00 64 61 72 69 65 73 20 21  S.......daries !

00DFE7A5    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00DFEA74    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90.00E1B9BD

00E1B9BD  7B 1A DF 00                                      {.ß.

00DFED0E    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 3
00DF7787    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 2
00DF7A49    8B0485 3687DE00 MOV EAX,DWORD PTR DS:[EAX*4+DE8736]		; eax = 0x53
00DF7CF9    0FB64E 03       MOVZX ECX,BYTE PTR DS:[ESI+3]		; ecx = 0
00DF7FC4   /FF248D E9B9E100 JMP DWORD PTR DS:[ECX*4+E1B9E9]          	; 0x90.00DF7FCB
00DF8266    0FB64E 04       MOVZX ECX,BYTE PTR DS:[ESI+4]		; ecx = 0
00DF8532    8B0C8D 3687DE00 MOV ECX,DWORD PTR DS:[ECX*4+DE8736]      	; 0x90.00E1BA65
00DF87CF    3001            XOR BYTE PTR DS:[ECX],AL			; al = 0x53, byte[ecx] = 0x51

00E1BA65  02 51 7E 72 99 FE 52 51 52 7C 8D 65 51 51 55 73

00DF8A6F    83C6 05         ADD ESI,5					; esi = 00E1BA59

00E1BA59  02 04 00 02

00DF8A72    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00DF8D16    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]		; edi = 00E1B9F5

00E1B9F5  6F E1 DE 00

00DF8FFA    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 04
00E0D4C6    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 0
00E0D76F    FF0485 3687DE00 INC DWORD PTR DS:[EAX*4+DE8736]          	; 0x90.00E1BA65

00DE8736  66 BA E1 00

00E0D776    0F85 76050000   JNZ 0x90.00E0DCF2
00E0DF7A    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1			; set to 1 to continue
00E0E229    83C6 03         ADD ESI,3					; esi = 00E1BA5C

00E1BA5C  02 03 03 04

00E0E4FA    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00E0E7C1    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90.00E1B9F5

00E1BA5C  02 03 03 04

00E0E7C8    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 3
00E09D76    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 3
00E0A03E    FF0C85 3687DE00 DEC DWORD PTR DS:[EAX*4+DE8736] 		; 20E

=> 00DE8742  0D 02 00 00

00E0A045    0F85 C6070000   JNZ 0x90.00E0A811				; 0x20E bytes to decrypt to quit 
                                                                        ; the loop
00E0AACC    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1			; set to 1 to continue and loop
00E0AD8F    83C6 03         ADD ESI,3					; esi = 00E1BA5F

00E1BA5F  04 01 16 00

00E0B06B    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 4
00E0B31E    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90.00E1BA29

00E1BA29  FD 34 E0 00

00E0B599    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 1
00E07C49    A1 4A87DE00     MOV EAX,DWORD PTR DS:[DE874A]		; eax = 1
00E07EF4    85C0            TEST EAX,EAX  				; test the value of the mark
00E07EF6    0F85 550B0000   JNZ 0x90.00E08A51
00E08CFE    8B76 02         MOV ESI,DWORD PTR DS:[ESI+2]		; esi = 16
00E08FC2    8DB6 3EBAE100   LEA ESI,DWORD PTR DS:[ESI+E1BA3E]		; esi = 00E1BA54

00E1BA54  01 03 02 00

00E0925F    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E09511    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90.00E1B9BD

00E1B9BD  7B 1A DF 00

00E097CF    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 3
00DF7787    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 2
00DF7A49    8B0485 3687DE00 MOV EAX,DWORD PTR DS:[EAX*4+DE8736]		; eax = 53
00DF7CF9    0FB64E 03       MOVZX ECX,BYTE PTR DS:[ESI+3]		; ecx = 0
00DF7FC4   /FF248D E9B9E100 JMP DWORD PTR DS:[ECX*4+E1B9E9]          	; 0x90.00DF7FCB
00DF8266    0FB64E 04       MOVZX ECX,BYTE PTR DS:[ESI+4]		; ecx = 0
00DF8532    8B0C8D 3687DE00 MOV ECX,DWORD PTR DS:[ECX*4+DE8736]      	; 0x90.00E1BA66

00E1BA66  51 7E 72 99

00DF87CF    3001            XOR BYTE PTR DS:[ECX],AL			; xor the next byte with 0x53

etc.

After the decryption, we can see some funny strings on it like :

eh?!
y!!!
nuts 
merc
driv
 no
its
show
Awai
hell

We will show later how they will be used.

All along the VM, there are a lot of SEH, used to clear Debug Registers, but the detection of tracing by checking the time with RDTSC disappeared (see above for the explanation).

00DEA4B6    8B4C24 0C       MOV ECX,DWORD PTR SS:[ESP+C]
00DEA4BA    33C0            XOR EAX,EAX
00DEA4BC    8941 04         MOV DWORD PTR DS:[ECX+4],EAX
00DEA4BF    8941 08         MOV DWORD PTR DS:[ECX+8],EAX
00DEA4C2    8941 0C         MOV DWORD PTR DS:[ECX+C],EAX
00DEA4C5    8941 10         MOV DWORD PTR DS:[ECX+10],EAX
00DEA4C8    8941 14         MOV DWORD PTR DS:[ECX+14],EAX
00DEA4CB    C741 18 5501000>MOV DWORD PTR DS:[ECX+18],155
00DEA4D2    8B81 B0000000   MOV EAX,DWORD PTR DS:[ECX+B0]
00DEA4D8    8BB9 9C000000   MOV EDI,DWORD PTR DS:[ECX+9C]
00DEA4DE    8B0487          MOV EAX,DWORD PTR DS:[EDI+EAX*4]
00DEA4E1    8981 B8000000   MOV DWORD PTR DS:[ECX+B8],EAX
00DEA4E7    33C0            XOR EAX,EAX
00DEA4E9    C3              RETN

Part of the code that takes the argument in the commandline (only the important instructions of the Virtual Machine are quoted here) :

00E081AF    83C6 06         ADD ESI,6					; esi = 00E1BA65
00E08458    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00E08734    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9F5
00E0873B    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 2
00DFDCAD    8B46 02         MOV EAX,DWORD PTR DS:[ESI+2]		; eax = ADCA212D

00E1BA67  2D 21 CA AD

00DFDF5E    05 04EDFDAE     ADD EAX,AEFDED04				; eax = 5CC80E31
00DFE20E    0FB67E 06       MOVZX EDI,BYTE PTR DS:[ESI+6]		; edi = 6
00DFE4DC    8904BD 3687DE00 MOV DWORD PTR DS:[EDI*4+DE8736],EAX

00DE873A  31 0E C8 5C

00DFE4E3    83C6 07         ADD ESI,7					; esi = 7
00DFE7A5    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00DFEA74    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9F5
00DFED0E    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 1
00DEEC12    8B46 02         MOV EAX,DWORD PTR DS:[ESI+2]		; eax = 0236DE2F
00DEEEC7    05 DE31A7FE     ADD EAX,FEA731DE				; eax = 00DE100D ; GetCommandLine
00DEF171    8B40 02         MOV EAX,DWORD PTR DS:[EAX+2]             	; 0x90_5bi.00E28060
00DEF411    8B00            MOV EAX,DWORD PTR DS:[EAX]               	; kernel32.GetCommandLineA
00DEF413    BF 4EF9DE00     MOV EDI,0x90_5bi.00DEF94E
00DEF418    2BC7            SUB EAX,EDI
00DEF69D    83E8 04         SUB EAX,4					; eax = 7706EA06
00DEF94C    AB              STOS DWORD PTR ES:[EDI] 			; address of GetcommandLine in eax

00DEF94E  06 EA 06 77

00DEF94D    E8 06EA0677     CALL kernel32.GetCommandLineA
00DEFC14    A3 3687DE00     MOV DWORD PTR DS:[DE8736],EAX 		; store the memory adress that
                                                                        ; points to the return value of 
                                                                        ; GetCommandLine
00DE8736  E0 1E 14 00

00141EE0  22 43 3A 5C 61 67 61 64 6F 75 5C 30 78 39 30 5F  "C:\agadou\0x90_
00141EF0  35 62 69 73 2E 65 78 65 22 00 AB AB AB AB AB AB  5bis.exe".««««««
00141F00  AB AB EE FE EE FE EE FE 00 00 00 00 00 00 00 00  ««îþîþîþ........
00141F10  5E 00 07 00 00 07 18 00 08 22 14 00 38 25 14 00  ^........"..8%..
00141F20  00 00 28 00 0C 00 00 00 3A 17 2B 00              ..(.....:.+.

00DEFEBA    85C0            TEST EAX,EAX				; test if the function succeed
00DEFEBC    0F85 080B0000   JNZ 0x90_5bi.00DF09CA
00DF0C4B    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1			; set the mark to 1 to continue
00DF0F24    83C6 06         ADD ESI,6					; esi = 00E1BA72
00DF11F0    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00DF11F3    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9F5
00DF14B2    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 6
00E15DBC    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 20
00E16049    8B3D 3687DE00   MOV EDI,DWORD PTR DS:[DE8736]		; edi = pointer to return value
00E162EE    0FB74E 03       MOVZX ECX,WORD PTR DS:[ESI+3]		; ecx = 255
00E1658B    F2:AE           REPNE SCAS BYTE PTR ES:[EDI]		; scan 255 bytes to find a 
                                                                        ; space char (0x20) in the return 
                                                                        ; value of GetCommandLine
00E16843    85C9            TEST ECX,ECX				; if space char found, ecx != 0
00E16845    0F84 070B0000   JE 0x90_5bi.00E17352
00E16AF2    893D 3687DE00   MOV DWORD PTR DS:[DE8736],EDI		; pointer to the argument

00DE8736  F9 1E 14 00

00141EF9  31 32 33 34 22 00                                1234".

00E16DCB    68 08DDE000     PUSH 0x90_5bi.00E0DD08
00E1707F    810424 54960000 ADD DWORD PTR SS:[ESP],9654

00E0DD08 + 9654 = 00E1735C

00E1735C    83C6 05         ADD ESI,5					; esi = 00E1BA77

00E1BA77  04 02 2E 01        

00E1735F    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 4
00E17362    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1BA29
00E17369    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 2
00E0FB4D    A1 4A87DE00     MOV EAX,DWORD PTR DS:[DE874A]		; eax = 1
00E0FE17    85C0            TEST EAX,EAX				; test the mark
00E0FE19    0F84 4D0B0000   JE 0x90_5bi.00E1096C
00E0FE1F    83C6 06         ADD ESI,6					; esi = 00E1BA7D
00E100EB    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00E103B6    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9F5
00E1067F    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 8
00E0EAE9    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 0
00E0ED84    8B0485 3687DE00 MOV EAX,DWORD PTR DS:[EAX*4+DE8736]		; eax = pointer to the argument
00E0F030    8B00            MOV EAX,DWORD PTR DS:[EAX]			; eax = hexa value of the first 4 bytes

00141EF9  31 32 33 34                                      1234

eax = 34333231

00E0F032    0FB67E 03       MOVZX EDI,BYTE PTR DS:[ESI+3]		; edi = 2
00E0F2E0    8904BD 3687DE00 MOV DWORD PTR DS:[EDI*4+DE8736],EAX		; store hexa values in memory

00DE873E  31 32 33 34 00 00                                1234..

3. Provide a means to "quickly" analyse this uncommon feature.

I traced all the instructions manually in the VM, but an easy way to keep only the important instructions is to find "popad" and "pushad" instructions and to look between them only.
This instruction, between "popad" and "pushad" are clear, without obfuscation, that's why it is not difficult to understand what happens... just very long.
Moreover Nicolas brulez played with the eax register primarily : sometimes it is xored with 0x66 (when eax = 0x66 ) so, eax is set to 0 but indirectly ; sometimes it substracts or adds 1, 2, 3, 4 or 5 to eax to have the correct value.
In short the opcodes stored in memory sometimes needs to be modified to have a correct value.

4. Which tools are the most suited for analysing such binaries, and why ?

For analysing binaries, I think the tools that can be usefull are :

I think the tools the most suited for analysing binaries like 0x90 are IDA or Ollydbg (ollyscript installed) : it allows us to write some scripts to decrypt the layers, to clear obfuscation code, etc.
With IDC scripts or Ollyscript, we don't need to write our own tools.
Moreover there is a interessant plugin for IDA too : ida-x86emu . This one will trace the the code for us. It is usefull when they are a lot of detection code and junk code.
However I decided not to automate the decryption, I prefered to trace all the code manually : automate the decryption of the layers in this binary was not easy as well...

5. Identify the purpose (fictitious or not) of the binary.

The purpose of this binary is to wait for a correct password in order to access anything... here it only shows us a string (a message that will tell us we succeed) when we enter a good pass. But the binary could have fonctionnalities reserved to one person only : administration of a server (a malware binary like a trojan), securisation of sensible informations etc.

6. What is the binary waiting from the user? Please detail how you found it.

The binary is waiting a password from the user which allows us to authenticate. I am going to explain how I found it.

Part of the code that tests the argument entered (only the important instructions of the Virtual Machine are quoted here) :

We will used as notations :
_first_ for the first 4 bytes (in hexadecimal) of the argument entered (example : "1234" => _first_ = 34333231).
_second_ for the second value we will be used below (see later)

00E0F2E7    83C6 04         ADD ESI,4					; esi = 00E1BA81
00E0F5A1    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E0F5A4    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E0F859    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 4
00E18478    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 5
00E18721    83E8 03         SUB EAX,3					; eax = 2
00E189C0    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = _first_
00E18C5F    8B7E 03         MOV EDI,DWORD PTR DS:[ESI+3]		; edi = 1D9BDC45
00E18F2C    03DF            ADD EBX,EDI					; ebx = _first_ + edi

_first_(1) = _first_ + 1D9BDC45

00E18F2E    0F85 E6020000   JNZ 0x90_5bi.00E1921A			; jmp if != 0
00E1921A    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1			; set mark to 1
00E19502    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX		; set _first_(1) in memory
00E197AA    83C6 07         ADD ESI,7					; esi = 00E1BA88

00E1BA88  01 04 04 45

00E19A7D    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E19D3A    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E1A00D    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 4
00E18478    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 4
00E18721    83E8 03         SUB EAX,3					; eax = 1
00E189C0    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = 5CC80E31

00DE8736  F9 1E 14 00 31 0E C8 5C 76 0E CF 51 00 00 00 00

_second_ = 5CC80E31 (it is a constant value)

00E18C5F    8B7E 03         MOV EDI,DWORD PTR DS:[ESI+3]		; edi = 74519745
00E18F2C    03DF            ADD EBX,EDI

_second_(1) = 74519745 + _second_

00E19502    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX		; set _second_(1) in memory
00E197AA    83C6 07         ADD ESI,7					; esi = 00E1BA8F

00E1BA8F  01 05 04 E2

00E19A7D    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E19D3A    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E1A00D    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 5
00E1A2DA    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 4
00E1A582    83E8 02         SUB EAX,2					; eax = 2
00E1A852    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = _second_(1)
00E1AB03    8B7E 03         MOV EDI,DWORD PTR DS:[ESI+3]		; edi = AD45DFE2

00E1BA92  E2 DF 45 AD

00E1ADD3    2BDF            SUB EBX,EDI

_first_(2) = _second_(1) - AD45DFE2

00E1ADD5    75 09           JNZ SHORT 0x90_5bi.00E1ADE0			; jmp
00E1ADD7    8325 4A87DE00 0>AND DWORD PTR DS:[DE874A],0
00E1ADDE    EB 0A           JMP SHORT 0x90_5bi.00E1ADEA
00E1ADE0    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1			; set mark to 1
00E1B05F    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX		; set _first_(2) in memory
00E1B066    83C6 07         ADD ESI,7					; esi = 00E1BA96
00E1B069    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax= 1
00E1B06C    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E1B073    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 4
00E18478    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 4
00E18721    83E8 03         SUB EAX,3					; eax = 1
00E189C0    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = _second_(1)
00E18C5F    8B7E 03         MOV EDI,DWORD PTR DS:[ESI+3]		; edi = DEADBEEF
00E18F2C    03DF            ADD EBX,EDI

_second_(2) = DEADBEEF + _second_(1)

00E18F2E   /0F85 E6020000   JNZ 0x90_5bi.00E1921A			; jmp
00E1921A    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1			; set mark to 1
00E19502    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX		; set _second_(2) in memory
00E197AA    83C6 07         ADD ESI,7					; esi = 00E1BA9D
00E19A7D    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E19D3A    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E1A00D    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 4
00E18478    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 5
00E18721    83E8 03         SUB EAX,3					; eax = 2
00E189C0    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = _first_(2)
00E18C5F    8B7E 03         MOV EDI,DWORD PTR DS:[ESI+3]		; edi = 68656C6C (hell)
00E18F2C    03DF            ADD EBX,EDI

_first_(3) = 68656C6C (hell) + _first_(2)

00E1921A    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1			; set mark to 1
00E19502    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX		; set _first_(3) in memory
00E197AA    83C6 07         ADD ESI,7					; esi = 00E1BAA4
00E19A7D    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E19D3A    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E1A00D    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 5
00E1A2DA    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 3
00E1A582    83E8 02         SUB EAX,2					; eax =1
00E1A852    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = _second_(2)
00E1AB03    8B7E 03         MOV EDI,DWORD PTR DS:[ESI+3]		; edi = 17854165

00E1BAA7  65 41 85 17

00E1ADD3    2BDF            SUB EBX,EDI

_second_(3) =  _second_(2) - 17854165

00E1ADD5   /75 09           JNZ SHORT 0x90_5bi.00E1ADE0
00E1ADD7   |8325 4A87DE00 0>AND DWORD PTR DS:[DE874A],0
00E1ADDE   |EB 0A           JMP SHORT 0x90_5bi.00E1ADEA
00E1ADE0   \C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1
00E1B05F    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX		; set _second_(3) in memory
00E1B066    83C6 07         ADD ESI,7					; esi = 00E1BAAB
00E1B069    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E1B06C    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E1B073    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 5
00E1A2DA    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 4
00E1A582    83E8 02         SUB EAX,2					; eax = 2
00E1A852    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = _first_(3)
00E1AB03    8B7E 03         MOV EDI,DWORD PTR DS:[ESI+3]		; edi = 41776169 (Awai)
00E1ADD3    2BDF            SUB EBX,EDI

_first_(4) = _first_(3) - 41776169 (Awai)

00E1ADD5    75 09           JNZ SHORT 0x90_5bi.00E1ADE0
00E1ADD7    8325 4A87DE00 0>AND DWORD PTR DS:[DE874A],0
00E1ADDE    EB 0A           JMP SHORT 0x90_5bi.00E1ADEA
00E1ADE0    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1
00E1B05F    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX		; set _first_(4) in memory
00E1B066    83C6 07         ADD ESI,7					; esi = 00E1BAB2
00E1B069    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E1B06C    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E1B073    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 4
00E18478    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 4
00E18721    83E8 03         SUB EAX,3					; eax = 1
00E189C0    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = _second_(3)
00E18C5F    8B7E 03         MOV EDI,DWORD PTR DS:[ESI+3]		; edi = 73686F77 (show)
00E18F2C    03DF            ADD EBX,EDI

_second_(4) = _second_(3) + 73686F77 (show)

00E18F2E   /0F85 E6020000   JNZ 0x90_5bi.00E1921A
00E1921A    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1
00E19502    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX		; set _second_(4) in memory
00E197AA    83C6 07         ADD ESI,7					; esi = 00E1BAB9

00E1BAB9           20 73 74 69

00E19D3A    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E1A00D    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 4
00E18478    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 5
00E18721    83E8 03         SUB EAX,3					; eax = 2
00E189C0    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = _first_(4)
00E18C5F    8B7E 03         MOV EDI,DWORD PTR DS:[ESI+3]		; edi = 69747320 (its )
00E18F2C    03DF            ADD EBX,EDI

_first_(5) = add _first_(4) + 69747320 (its )

00E18F2E    0F85 E6020000   JNZ 0x90_5bi.00E1921A
00E1921A    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1
00E19502    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX		; set _first_(5) in memory
00E197AA    83C6 07         ADD ESI,7					; esi = 00E1BAC0

00E1BAC0  01 05 03 20

00E19A7D    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E19D3A    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E1A00D    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 5
00E1A2DA    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 3
00E1A582    83E8 02         SUB EAX,2					; eax = 1
00E1A852    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = _second_(4)
00E1AB03    8B7E 03         MOV EDI,DWORD PTR DS:[ESI+3]		; edi = 206E6F20 ( no )
00E1ADD3    2BDF            SUB EBX,EDI

_second_(5) = _second_(4) - 206E6F20 ( no )

00E1ADD5    75 09           JNZ SHORT 0x90_5bi.00E1ADE0
00E1ADD7    8325 4A87DE00 0>AND DWORD PTR DS:[DE874A],0
00E1ADDE    EB 0A           JMP SHORT 0x90_5bi.00E1ADEA
00E1ADE0    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1
00E1B05F    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX		; set _second_(5) in memory
00E1B066    83C6 07         ADD ESI,7					; esi = 00E1BAC7
00E1B069    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E1B06C    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E1B073    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 4
00E18478    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 5

00E1BAE9              FF FF FF DF

00E189C0    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = _first_(5)
00E18C5F    8B7E 03         MOV EDI,DWORD PTR DS:[ESI+3]		; edi = 64726976 (driv)
00E18F2C    03DF            ADD EBX,EDI

_first_(6) = _first_(5) + 64726976 (driv)

00E18F2E    0F85 E6020000   JNZ 0x90_5bi.00E1921A
00E19502    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX		; set _first_(6) in memory
00E197AA    83C6 07         ADD ESI,7					; esi = 00E1BACE
00E19A7D    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E19D3A    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E1A00D    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 4
00E18478    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 4
00E18721    83E8 03         SUB EAX,3					; eax = 1
00E189C0    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = _second_(5)
00E18C5F    8B7E 03         MOV EDI,DWORD PTR DS:[ESI+3]		; edi = 6D657263 (merc)
00E18F2C    03DF            ADD EBX,EDI

_second_(6) = _second_(5) + 6D657263 (merc)

00E18F2E    0F85 E6020000   JNZ 0x90_5bi.00E1921A
00E19502    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX		; set _second_(6) in memory
00E197AA    83C6 07         ADD ESI,7					; esi = 00E1BAD5
00E19A7D    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E19D3A    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E1A00D    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 5
00E1A2DA    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 4
00E1A582    83E8 02         SUB EAX,2					; eax = 2
00E1A852    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = _first_(6)
00E1AB03    8B7E 03         MOV EDI,DWORD PTR DS:[ESI+3]		; edi = 6E757473 (nuts)
00E1ADD3    2BDF            SUB EBX,EDI

_first_(7) = _first_(6) - 6E757473 (nuts)

00E1ADD5    75 09           JNZ SHORT 0x90_5bi.00E1ADE0
00E1ADD7    8325 4A87DE00 0>AND DWORD PTR DS:[DE874A],0
00E1ADDE    EB 0A           JMP SHORT 0x90_5bi.00E1ADEA
00E1ADE0    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1
00E1B05F    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX		; set _first_(7) in memory
00E1B066    83C6 07         ADD ESI,7					; esi = 00E1BADC
00E1B069    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E1B06C    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E1B073    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 5
00E1A2DA    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 3
00E1A582    83E8 02         SUB EAX,2					; eax = 1
00E1A852    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = _second_(6)
00E1AB03    8B7E 03         MOV EDI,DWORD PTR DS:[ESI+3]		; edi = 79212121 (y!!!)
00E1ADD3    2BDF            SUB EBX,EDI

_second_(7) = _second_(6) - 79212121 (y!!!)

00E1ADD5    75 09           JNZ SHORT 0x90_5bi.00E1ADE0
00E1ADD7    8325 4A87DE00 0>AND DWORD PTR DS:[DE874A],0
00E1ADDE    EB 0A           JMP SHORT 0x90_5bi.00E1ADEA
00E1ADE0    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1
00E1B05F    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX		; set _second_(7) in memory
00E1B066    83C6 07         ADD ESI,7					; esi = 00E1BAE3
00E1B069    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E1B06C    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E1B073    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 5
00E1A2DA    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 4
00E1A582    83E8 02         SUB EAX,2					; eax = 2
00E1A852    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = _first_(7)
00E1AB03    8B7E 03         MOV EDI,DWORD PTR DS:[ESI+3]		; edi = 65683F21 (eh?!)
00E1ADD3    2BDF            SUB EBX,EDI

_first_(8) = sub _first_(7) de 65683F21 (eh?!)

00E1ADD5    75 09           JNZ SHORT 0x90_5bi.00E1ADE0
00E1ADD7    8325 4A87DE00 0>AND DWORD PTR DS:[DE874A],0
00E1ADDE    EB 0A           JMP SHORT 0x90_5bi.00E1ADEA
00E1ADE0    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1
00E1B05F    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX		; set _first_(8) in memory
00E1B066    83C6 07         ADD ESI,7					; esi = 00E1BAEA
00E1B069    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E1B06C    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E1B073    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 6
00E12526    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 7
00E1252A    83E8 05         SUB EAX,5					; eax = 2
00E127B4    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = first_(8)
00E12A80    8B7E 03         MOV EDI,DWORD PTR DS:[ESI+3]		; edi = DFFFFFFF
00E12D2E    23DF            AND EBX,EDI

_first_(9) = _first_(8) AND DFFFFFFF

00E12D30    75 0C           JNZ SHORT 0x90_5bi.00E12D3E
00E12D32    8325 4A87DE00 0>AND DWORD PTR DS:[DE874A],0
00E12D39    E9 BB020000     JMP 0x90_5bi.00E12FF9
00E132EE    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX		; set _first_(9) in memory
00E132F5    83C6 07         ADD ESI,7					; esi = 00E1BAF1
00E132F8    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 0
00E132FB    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9A9
00E135B6    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 2
00E1766E    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 45 (E)
00E17920    83F0 47         XOR EAX,47					; eax = 2
00E17BF4    8B0485 3687DE00 MOV EAX,DWORD PTR DS:[EAX*4+DE8736]		; eax = _first_(9)
00E17EB7    50              PUSH EAX
00E18144    BB 0A000000     MOV EBX,0A
00E18149    83F3 09         XOR EBX,9
00E1814C    03F3            ADD ESI,EBX					; esi = 00E1BAF4
00E1814E    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 0
00E18151    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9A9
00E18158    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 2
00E1766E    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 46 (F)
00E17920    83F0 47         XOR EAX,47					; eax = 1
00E17BF4    8B0485 3687DE00 MOV EAX,DWORD PTR DS:[EAX*4+DE8736]		; eax = _second_(7)
00E17EB7    50              PUSH EAX
00E18144    BB 0A000000     MOV EBX,0A
00E18149    83F3 09         XOR EBX,9
00E1814C    03F3            ADD ESI,EBX					; esi = 00E1BAF7
00E1814E    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 3
00E18151    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1BA25
00E18158    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 0
00DFF2A3    8B0424          MOV EAX,DWORD PTR SS:[ESP]			; eax = _second_(7)
00DFF51B    3B4424 04       CMP EAX,DWORD PTR SS:[ESP+4]		; cmp _second_(7), _first_(9)
00DFF51F   /0F85 C0100000   JNZ 0x90_5bi.00E005E5			; if != 0 BadBoy

We have :

_first_(1) = 1D9BDC45 + _first_
_first_(2) = _second_(1) - AD45DFE2
_first_(3) = 68656C6C (hell) + _first_(2)
_first_(4) = _first_(3) - 41776169 (Awai)
_first_(5) = _first_(4) + 69747320 (its )
_first_(6) = _first_(5) + 64726976 (driv)
_first_(7) = _first_(6) - 6E757473 (nuts)
_first_(8) = _first_(7) - 65683F21 (eh?!)
_first_(9) = _first_(8) and DFFFFFFF

_second_(1) = 74519745 + _second_ (_second_ = 5CC80E31)
_second_(2) = DEADBEEF + _second_(1) (_second_(1) = D119A576)
_second_(3) = _second_(2) - 17854165 (_second_(2) = (1)AFC76465)
_second_(4) = _second_(3) + 73686F77 (show) (_second_(3) = 98422300)
_second_(5) = _second_(4) - 206E6F20 ( no ) (_second_(4) = (1)0BAA9277
_second_(6) = _second_(5) + 6D657263 (merc) (_second_(5) = EB3C2357)
_second_(7) = _second_(6) - 79212121 (y!!!) (_second_(6) = (1)58A195BA)

<=> _second_(7) = (((((((74519745+5CC80E31)+DEADBEEF)-17854165)+73686F77)-206E6F20)+6D657263)-79212121)
<=> _second_(7) = (1)DF807499

_first_(9) and _second_(7) needs to be equals (_second_(7) = DF807499)

So :

first_(9) = (1)DF807499
<=> _first_(8) = DF807499
<=> _first_(7) = DF807499 + 65683F21 = (1)44E8B3BA
<=> _first_(6) = (1)44E8B3BA + 6E757473 = B35E282D
<=> _first_(5) = B35E282D - 64726976 = 4EEBBEB7
<=> _first_(4) = (1)14EEBBEB7 - 69747320 = E5774B97
<=> _first_(3) = E5774B97 + 41776169 = (1)26EEAD00
<=> _first_(2) = (1)26EEAD00 - 68656C6C = BE894094
<=> _first_(1) = BE894094 + AD45DFE2 = (1)6BCF2076
<=> _first_ = 6BCF2076 - 1D9BDC45 = (1)4E334431 

0x3144334E in ascii = "1D3N" so the 4 first characters of the pass is "1D3N"
00DFF80F    83C4 08         ADD ESP,8
00DFFAC1    8B76 02         MOV ESI,DWORD PTR DS:[ESI+2]		; esi = 00E4DE3D
00DFFD4A    81EE 37130300   SUB ESI,31337				; esi = 00E1BB06
00DFFFF6    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00E002BA    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9F5
00E002C1    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 4
00E0D4C6    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 0
00E0D76F    FF0485 3687DE00 INC DWORD PTR DS:[EAX*4+DE8736]		; pointer to the next char of the 
                                                                        ; argument
00E0D776    0F85 76050000   JNZ 0x90_5bi.00E0DCF2
00E0DF7A    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1			; set mark to 1
00E0E229    83C6 03         ADD ESI,3					; esi = 00E1BB09
00E0E4FA    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E0E7C1    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E0E7C8    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 4
00E18478    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 3
00E18721    83E8 03         SUB EAX,3					; eax = 0
00E189C0    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = pointer to the 2nd char
00E18C5F    8B7E 03         MOV EDI,DWORD PTR DS:[ESI+3]		; edi = 2
00E18F2C    03DF            ADD EBX,EDI					; ebx = 00141EFB + 2
00E18F2E    0F85 E6020000   JNZ 0x90_5bi.00E1921A
00E1921A    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1			; set mark to 1
00E19502    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX		; ebx = pointer to the 4th char
00E197AA    83C6 07         ADD ESI,7					; esi = 00E1BB10
00E19A7D    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00E19D3A    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9F5
00E1A00D    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 4
00E0D76F    FF0485 3687DE00 INC DWORD PTR DS:[EAX*4+DE8736]
00E0D776    0F85 76050000   JNZ 0x90_5bi.00E0DCF2
00E0DF7A    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1			; set mark to 1
00E0E229    83C6 03         ADD ESI,3					; esi = 00E1BB13
00E0E4FA    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00E0E7C1    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9F5
00E0E7C8    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 0B
00E0402D    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]
00E042E6    8B0485 3687DE00 MOV EAX,DWORD PTR DS:[EAX*4+DE8736]		; eax = pointer to the 5th char
00E04588    0FB700          MOVZX EAX,WORD PTR DS:[EAX]			; eax = hexa value of (char6_char5)
00E04823    0FB67E 03       MOVZX EDI,BYTE PTR DS:[ESI+3]		; edi = 1
00E04ACD    8904BD 3687DE00 MOV DWORD PTR DS:[EDI*4+DE8736],EAX		; set 0000char6_char5 in memory
00E04D5F    83C6 04         ADD ESI,4					; esi = 00E1BB17
00E05059    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 0
00E0505C    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9A9
00E05305    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 2
00E1766E    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 46
00E17920    83F0 47         XOR EAX,47					; eax = 1
00E17BF4    8B0485 3687DE00 MOV EAX,DWORD PTR DS:[EAX*4+DE8736]		; eax = 0000char6_char5
00E17EB7    50              PUSH EAX
00E18144    BB 0A000000     MOV EBX,0A
00E18149    83F3 09         XOR EBX,9
00E1814C    03F3            ADD ESI,EBX					; esi = 00E1BB1A
00E1814E    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 0
00E18151    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9A9
00E18158    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 3
00E1B372    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]
00E1B376    83F0 66         XOR EAX,66					; eax = 2
00E1B64A    8F0485 3687DE00 POP DWORD PTR DS:[EAX*4+DE8736]		; set 0000char6_char5 in memory
00E1B8CF    83C6 04         ADD ESI,4
00E1B8D2    4E              DEC ESI					; esi = 00E1BB1D
00E1B8D3    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 0
00E1B8D6    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9A9
00E1B8DD    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 2
00E1766E    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 47
00E17920    83F0 47         XOR EAX,47					; eax = 0
00E17BF4    8B0485 3687DE00 MOV EAX,DWORD PTR DS:[EAX*4+DE8736]		; eax = pointer to 5th char
00E17EB7    50              PUSH EAX
00E18144    BB 0A000000     MOV EBX,0A
00E18149    83F3 09         XOR EBX,9
00E1814C    03F3            ADD ESI,EBX					; esi = 00E1BB20
00E1814E    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 0
00E18151    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9A9
00E18158    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 1
00DEC633    8B46 02         MOV EAX,DWORD PTR DS:[ESI+2]		; eax = 530822D6
00DEC8CD    05 3713D0AD     ADD EAX,ADD01337				; eax = 00D8360D
00DECB8A    50              PUSH EAX
00DECE37    B8 D1F5FFFF     MOV EAX,-0A2F				; eax = FFFFF5D1
00DED113    F7D0            NOT EAX					; eax = 0000A2E
00DED3BB    35 280A0000     XOR EAX,0A28				; eax = 6
00DED680    8D3406          LEA ESI,DWORD PTR DS:[ESI+EAX]		; esi = 00E1BB26
00DED936    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 0
00DEDC00    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9A9
00DEDE7F    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 3
00E1B372    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]
00E1B376    83F0 66         XOR EAX,66					; eax = 0
00E1B64A    8F0485 3687DE00 POP DWORD PTR DS:[EAX*4+DE8736]		; pointer to 5th char
00E1B8CF    83C6 04         ADD ESI,4
00E1B8D2    4E              DEC ESI					; esi = 00E1BB29
00E1B8D3    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E1B8D6    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E1B8DD    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 4
00E18478    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 3
00E18721    83E8 03         SUB EAX,3					; eax = 0
00E189C0    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = 00D8360D
00E18C5F    8B7E 03         MOV EDI,DWORD PTR DS:[ESI+3]		; edi = 00098548
00E18F2C    03DF            ADD EBX,EDI					; ebx = 00D8360D + 00098548 = 00E1BB55
00E18F2E    0F85 E6020000   JNZ 0x90_5bi.00E1921A
00E1921A    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1
00E19502    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX      	; 0x90_5bi.00E1BB55
00E197AA    83C6 07         ADD ESI,7					; esi = 00E1BB30
00E19A7D    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00E19D3A    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9F5
00E1A00D    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 3
00E09D76    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 0
00E0A03E    FF0C85 3687DE00 DEC DWORD PTR DS:[EAX*4+DE8736]          	; 0x90_5bi.00E1BB55 (get G (47))
00E0AACC    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1			; set mark to 1
00E0AD8F    83C6 03         ADD ESI,3					; esi = 00E1BB33
00E0B06B    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E0B31E    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E0B599    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 3
00DF7787    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 2
00DF7A49    8B0485 3687DE00 MOV EAX,DWORD PTR DS:[EAX*4+DE8736]		; eax = 0000char6_char5
00DF7CF9    0FB64E 03       MOVZX ECX,BYTE PTR DS:[ESI+3]		; ecx = 1
00DF7FC4   /FF248D E9B9E100 JMP DWORD PTR DS:[ECX*4+E1B9E9]          	; 0x90_5bi.00DF9048
00DF92E8    0FB64E 04       MOVZX ECX,BYTE PTR DS:[ESI+4]		; ecx = 0
00DF9593    8B0C8D 3687DE00 MOV ECX,DWORD PTR DS:[ECX*4+DE8736]      	; 0x90_5bi.00E1BB54
00DF9848    66:3101         XOR WORD PTR DS:[ECX],AX			; 4247 xor char6_char5

5eme char xor 47 (G)
6eme char xor 42 (B)

00DF9AE6    83C6 05         ADD ESI,5					; esi = 00E1BB38
00DF9D86    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 0
00DFA043    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9A9
00DFA2CB    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 3
00E1B372    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]
00E1B376    83F0 66         XOR EAX,66					; eax = 0
00E1B64A    8F0485 3687DE00 POP DWORD PTR DS:[EAX*4+DE8736]          	; pointer to 5th char
00E1B8CF    83C6 04         ADD ESI,4
00E1B8D2    4E              DEC ESI					; esi = 00E1BB3B
00E1B8D3    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00E1B8D6    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9F5
00E1B8DD    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 0A
00E0B8C1    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 0
00E0B8C5    8B0485 3687DE00 MOV EAX,DWORD PTR DS:[EAX*4+DE8736]		; eax = pointer to 5th char
00E0BB76    0FB600          MOVZX EAX,BYTE PTR DS:[EAX]			; eax = hexa value of the 5th char
00E0BE33    0FB67E 03       MOVZX EDI,BYTE PTR DS:[ESI+3]		; edi = 2
00E0C0C0    8904BD 3687DE00 MOV DWORD PTR DS:[EDI*4+DE8736],EAX		; set the 5th char in memory
00E0C3C4    83C6 04         ADD ESI,4					; esi = 00E1BB3F
00E0C3C7    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E0C674    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E0C67B    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 4
00E18478    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 3
00E18721    83E8 03         SUB EAX,3					; eax = 0
00E189C0    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = pointer to 5th char
00E18C5F    8B7E 03         MOV EDI,DWORD PTR DS:[ESI+3]		; edi = 2
00E18F2C    03DF            ADD EBX,EDI					; ebx = pointer to 7th char
00E18F2E    0F85 E6020000   JNZ 0x90_5bi.00E1921A
00E1921A    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1
00E19502    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX		; set pointer to 7th char in memory
00E197AA    83C6 07         ADD ESI,7					; esi = 00E1BB46
00E19A7D    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00E19D3A    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9F5
00E1A00D    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]
00E0B8C1    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 0
00E0B8C5    8B0485 3687DE00 MOV EAX,DWORD PTR DS:[EAX*4+DE8736]		; eax = pointer to 7th char
00E0BB76    0FB600          MOVZX EAX,BYTE PTR DS:[EAX]			; eax = hexa value of the 7th char
00E0BE33    0FB67E 03       MOVZX EDI,BYTE PTR DS:[ESI+3]		; edi = 1
00E0C0C0    8904BD 3687DE00 MOV DWORD PTR DS:[EDI*4+DE8736],EAX		; set 000000char7 in memory
00E0C3C4    83C6 04         ADD ESI,4					; esi = 00E1BB4A
00E0C3C7    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E0C674    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E0C67B    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 9
00E055EA    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 2
00E058B1    48              DEC EAX					; eax = 1
00E05B4B    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = hexa value of the 7th char
00E05DFF    0FB646 03       MOVZX EAX,BYTE PTR DS:[ESI+3]		; eax = 5
00E060DF    83E8 03         SUB EAX,3					; eax = 2
00E0636D    8B3C85 3687DE00 MOV EDI,DWORD PTR DS:[EAX*4+DE8736]		; edi = hexa value of the 5th char
00E06610    03FB            ADD EDI,EBX

edi = 000000char5 + 000000char7 = 000000char5_7

00E06612    0F85 3C050000   JNZ 0x90_5bi.00E06B54
00E06E08    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1			; set mark to 1
00E070E0    893C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EDI		; set 000000char5_7 in memory
00E070E7    83C6 04         ADD ESI,4					; esi = 00E1BB4E
00E07390    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 5
00E07680    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1BA35
00E07687    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 0
00E1389E    8B46 02         MOV EAX,DWORD PTR DS:[ESI+2]             	; 0x90_5bi.00E1BB86
00E13B63    8D7E 06         LEA EDI,DWORD PTR DS:[ESI+6]		; edi = 00E1BB54
00E13B66    57              PUSH EDI
00E13E36    8BF0            MOV ESI,EAX                              	; 0x90_5bi.00E1BB86
00E13E38    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00E13E3B    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9F5
00E140DA    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 2
00DFDF5E    05 04EDFDAE     ADD EAX,AEFDED04

eax = 51021348
=> eax = 51021348 + AEFDED04 = 0000004C

00DFE20E    0FB67E 06       MOVZX EDI,BYTE PTR DS:[ESI+6]		; edi = 1
00DFE4DC    8904BD 3687DE00 MOV DWORD PTR DS:[EDI*4+DE8736],EAX		; set 0000004C in memory
00DFE4E3    83C6 07         ADD ESI,7					; esi = 00E1BB8D
00DFE7A5    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00DFEA74    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9F5
00DFED0E    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 4
00E0D76F    FF0485 3687DE00 INC DWORD PTR DS:[EAX*4+DE8736]		; 0000004C + 1 = 0000004D
00E0D776   /0F85 76050000   JNZ 0x90_5bi.00E0DCF2
00E0DF7A    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1			; set mark to 1
00E0E229    83C6 03         ADD ESI,3					; esi = 00E1BB90
00E0E4FA    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00E0E7C1    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9F5
00E0E7C8    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 4
00E0D76F    FF0485 3687DE00 INC DWORD PTR DS:[EAX*4+DE8736]		; 0000004D + 1 = 0000004E
00E0D776    0F85 76050000   JNZ 0x90_5bi.00E0DCF2
00E0DF7A    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1			; set mark to 1
00E0E229    83C6 03         ADD ESI,3					; esi = 00E1BB93
00E0E4FA    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E0E7C1    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E0E7C8    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 4
00E18478    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 4
00E18721    83E8 03         SUB EAX,3					; eax = 1
00E189C0    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = 0000004E
00E18C5F    8B7E 03         MOV EDI,DWORD PTR DS:[ESI+3]		; edi = 00000005
00E18F2C    03DF            ADD EBX,EDI					; ebx = 0000004E + 00000005 = 00000053
00E18F2E    0F85 E6020000   JNZ 0x90_5bi.00E1921A
00E1921A    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1			; set mark to 1
00E19502    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX		; set 00000053 in memory
00E197AA    83C6 07         ADD ESI,7					; esi = 00E1BB9A
00E19A7D    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00E19D3A    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9F5
00E1A00D    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 3
00E09D76    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 1
00E0A03E    FF0C85 3687DE00 DEC DWORD PTR DS:[EAX*4+DE8736]		; 00000053 - 1 = 00000052
00E0A045    0F85 C6070000   JNZ 0x90_5bi.00E0A811
00E0AACC    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1			; set mark to 1
00E0AD8F    83C6 03         ADD ESI,3					; esi = 00E1BB9D
00E0B31E    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E1A2DA    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 3
00E1A582    83E8 02         SUB EAX,2					; eax = 1
00E1A852    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = 00000052
00E1ADD3    2BDF            SUB EBX,EDI					; 00000052 - 00000004 = 0000004E
00E1ADD5    75 09           JNZ SHORT 0x90_5bi.00E1ADE0
00E1ADD7    8325 4A87DE00 0>AND DWORD PTR DS:[DE874A],0
00E1ADDE    EB 0A           JMP SHORT 0x90_5bi.00E1ADEA
00E1ADE0    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1			; set mark to 1
00E1ADEA    60              PUSHAD
00E1B05F    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX		; set 0000004E in memory
00E1B066    83C6 07         ADD ESI,7					; esi = 00E1BBA4
00E1B069    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E1B06C    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E1B073    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 5
00E1A2DA    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 4
00E1A582    83E8 02         SUB EAX,2					; eax = 2
00E1A852    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = 000000char5_7
00E1AB03    8B7E 03         MOV EDI,DWORD PTR DS:[ESI+3]		; edi = 0000005A
00E1ADD3    2BDF            SUB EBX,EDI

ebx = 000000char5_7 - 0000005A = 000000char5_7(1)

00E1ADD5    75 09           JNZ SHORT 0x90_5bi.00E1ADE0
00E1ADD7    8325 4A87DE00 0>AND DWORD PTR DS:[DE874A],0
00E1ADDE    EB 0A           JMP SHORT 0x90_5bi.00E1ADEA
00E1ADE0    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1			; set mark to 1
00E1B05F    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX		; set 000000char5_7(1) in memory
00E1B066    83C6 07         ADD ESI,7					; esi = 00E1BBAB
00E1B069    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E1B073    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 0A
00DFBBE6    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 4
00DFBEAA    83E8 02         SUB EAX,2					; eax = 2
00DFBEAD    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = 000000char5_7(1)
00DFC166    0FB646 03       MOVZX EAX,BYTE PTR DS:[ESI+3]		; eax = 2
00DFC41D    48              DEC EAX					; eax = 1
00DFC6C7    8B3C85 3687DE00 MOV EDI,DWORD PTR DS:[EAX*4+DE8736]		; edi = 0000004E
00DFC98A    3BFB            CMP EDI,EBX

So we need :
000000char5_7(1) = 0000004E
<=> (000000char5 + 000000char7) - 0000005A = 0000004E

The possible values for char5 and char7 are :
(000000char5 + 000000char7) = 000000A8

* and ~ 
+ and }
, and |
- and {
. and z
/ and y
0 and x
1 and w
2 and v
3 and u
4 and t
5 and s
6 and r
7 and q
8 and p
9 and o
: and n
; and m
< and l
= and k
> and j
? and i
@ and h
A and g
B and f
C and e
D and d
E and c
F and b
G and a
H and `
I and _
J and ^
K and ]
L and \
M and [
N and Z
O and Y
P and X
Q and W
R and V
S and U
T and T
00DFC98C    0F85 6B050000   JNZ 0x90_5bi.00DFCEFD
00DFCC35    8325 4A87DE00 0>AND DWORD PTR DS:[DE874A],0
00DFD18C    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX		; set 000000char5_7(1) in memory
00DFD43F    83C6 04         ADD ESI,4					; esi = 00E1BBAF
00DFD442    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 4
00DFD703    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1BA29
00DFD9B0    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 1
00E07C49    A1 4A87DE00     MOV EAX,DWORD PTR DS:[DE874A]		; eax = value of the mark
00E07EF4    85C0            TEST EAX,EAX				; test the value of the mark
00E07EF6    0F85 550B0000   JNZ 0x90_5bi.00E08A51

00E081AF    83C6 06         ADD ESI,6					; esi = 00E1BBB5
00E08458    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00E08734    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9F5
00E0873B    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 3
00E09D76    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 0
00E0A03E    FF0C85 3687DE00 DEC DWORD PTR DS:[EAX*4+DE8736]		; pointer to the 6th char
00E0A045    0F85 C6070000   JNZ 0x90_5bi.00E0A811
00E0AACC    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1			; set mark to 1
00E0AD8F    83C6 03         ADD ESI,3					; esi = 00E1BBB8
00E0B06B    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00E0B31E    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9F5
00E0B599    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 0A
00E0B8C1    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 0
00E0BB76    0FB600          MOVZX EAX,BYTE PTR DS:[EAX]			; eax = 000000char6
00E0BE33    0FB67E 03       MOVZX EDI,BYTE PTR DS:[ESI+3]		; edi = 2
00E0C3C4    83C6 04         ADD ESI,4					; esi = 00E1BBBC
00E0C3C7    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E0C674    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E0C67B    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 4
00E18478    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 3
00E18721    83E8 03         SUB EAX,3					; eax = 0
00E189C0    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = pointer to the 6th char
00E18C5F    8B7E 03         MOV EDI,DWORD PTR DS:[ESI+3]		; edi = 2
00E18F2C    03DF            ADD EBX,EDI					; ebx = pointer to the 8th char
00E18F2E    0F85 E6020000   JNZ 0x90_5bi.00E1921A
00E1921A    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1			; set mark to 1
00E19502    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX		; set pointer to the 8th char in memory
00E197AA    83C6 07         ADD ESI,7					; esi = 00E1BBC3
00E19A7D    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00E19D3A    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9F5
00E1A00D    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 0A
00E0B8C1    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 0
00E0B8C5    8B0485 3687DE00 MOV EAX,DWORD PTR DS:[EAX*4+DE8736]		; addresse pointe 8eme char
00E0BB76    0FB600          MOVZX EAX,BYTE PTR DS:[EAX]			; eax = 000000char8
00E0BE33    0FB67E 03       MOVZX EDI,BYTE PTR DS:[ESI+3]		; edi = 1
00E0C0C0    8904BD 3687DE00 MOV DWORD PTR DS:[EDI*4+DE8736],EAX		; set 000000char8 in memory
00E0C3C4    83C6 04         ADD ESI,4					; esi = 00E1BBC7
00E0C3C7    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E0C674    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E0C67B    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 9
00E055EA    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 2
00E058B1    48              DEC EAX					; eax = 1
00E05B4B    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = 000000char8
00E05DFF    0FB646 03       MOVZX EAX,BYTE PTR DS:[ESI+3]		; eax = 5
00E060DF    83E8 03         SUB EAX,3					; eax = 2
00E0636D    8B3C85 3687DE00 MOV EDI,DWORD PTR DS:[EAX*4+DE8736]		; edi = 000000char6
00E06610    03FB            ADD EDI,EBX

edi = 000000char6 + 000000char8 = 000000char6_8

00E06612    0F85 3C050000   JNZ 0x90_5bi.00E06B54
00E06E08    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1
00E070E0    893C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EDI		; set 000000char6_8 in memory
00E070E7    83C6 04         ADD ESI,4					; esi = 00E1BBCB
00E07390    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00E07680    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9F5
00E07687    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 4
00E0D76F    FF0485 3687DE00 INC DWORD PTR DS:[EAX*4+DE8736]

000000char6_8(1) = 000000char6_8 + 1

00E0D776    0F85 76050000   JNZ 0x90_5bi.00E0DCF2
00E0DF7A    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1
00E0E229    83C6 03         ADD ESI,3					; esi = 00E1BBCE
00E0E4FA    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E0E7C1    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E0E7C8    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 5
00E1A2DA    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 4
00E1A582    83E8 02         SUB EAX,2					; eax = 2
00E1A852    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]		; ebx = 000000char6_8(1)
00E1AB03    8B7E 03         MOV EDI,DWORD PTR DS:[ESI+3]		; edi = 000000char5_7(1) = 0000004E
00E1ADD3    2BDF            SUB EBX,EDI

000000char6_8(2) = 000000char6_8(1) - 000000char5_7(1)
<=> 000000char6_8(2) = 000000char6_8(1) - 0000004E

00E1ADD5    75 09           JNZ SHORT 0x90_5bi.00E1ADE0
00E1ADD7    8325 4A87DE00 0>AND DWORD PTR DS:[DE874A],0
00E1ADDE    EB 0A           JMP SHORT 0x90_5bi.00E1ADEA
00E1ADE0    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1			; set mark to 1
00E1B05F    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX		; set 000000char6_8(2) in memory
00E1B066    83C6 07         ADD ESI,7					; esi = 00E1BBD5
00E1B069    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 0
00E1B06C    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9A9
00E1B073    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 1
00DEC633    8B46 02         MOV EAX,DWORD PTR DS:[ESI+2]		; eax = 5310CA2D
00DEC8CD    05 3713D0AD     ADD EAX,ADD01337				; eax = 00E0DD64
00DECB8A    50              PUSH EAX                                 	; 0x90_5bi.00E0DD64
00DECE37    B8 D1F5FFFF     MOV EAX,-0A2F				; eax = FFFFF5D1
00DED113    F7D0            NOT EAX					; eax = 00000A2E
00DED3BB    35 280A0000     XOR EAX,0A28				; eax = 00000006
00DED680    8D3406          LEA ESI,DWORD PTR DS:[ESI+EAX]		; esi = 00E1BBDB
00DED936    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 0
00DEDC00    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9A9
00DEDE7F    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 3
00E1B372    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 66
00E1B376    83F0 66         XOR EAX,66					; eax = 0
00E1B64A    8F0485 3687DE00 POP DWORD PTR DS:[EAX*4+DE8736]          	; 0x90_5bi.00E0DD64
00E1B8CF    83C6 04         ADD ESI,4
00E1B8D2    4E              DEC ESI					; esi = 00E1BBDE
00E1B8D3    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E1B8D6    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E1B8DD    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 4
00E18478    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 3
00E18721    83E8 03         SUB EAX,3					; eax = 0
00E189C0    8B1C85 3687DE00 MOV EBX,DWORD PTR DS:[EAX*4+DE8736]      	; 0x90_5bi.00E0DD64
00E18C5F    8B7E 03         MOV EDI,DWORD PTR DS:[ESI+3]		; edi = 0000DEAC
00E18F2C    03DF            ADD EBX,EDI					; 00E0DD64 + 0000DEAC = 00E1BC10
00E18F2E    0F85 E6020000   JNZ 0x90_5bi.00E1921A
00E19502    891C85 3687DE00 MOV DWORD PTR DS:[EAX*4+DE8736],EBX      	; 0x90_5bi.00E1BC10
00E197AA    83C6 07         ADD ESI,7					; esi = 00E1BBE5
00E19A7D    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00E19D3A    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9F5
00E1A00D    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]
00E0D76F    FF0485 3687DE00 INC DWORD PTR DS:[EAX*4+DE8736]          	; 0x90_5bi.00E1BC10
00E0D776    0F85 76050000   JNZ 0x90_5bi.00E0DCF2
00E0DF7A    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1			; set mark to 1
00E0E229    83C6 03         ADD ESI,3					; esi = 00E1BBE8
00E0E4FA    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E0E7C1    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E0E7C8    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 3
00DF7787    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 2
00DF7A49    8B0485 3687DE00 MOV EAX,DWORD PTR DS:[EAX*4+DE8736]		; eax = 000000char6_8(2)
00DF7CF9    0FB64E 03       MOVZX ECX,BYTE PTR DS:[ESI+3]		; ecx = 0
00DF7FC4   /FF248D E9B9E100 JMP DWORD PTR DS:[ECX*4+E1B9E9]          	; 0x90_5bi.00DF7FCB
00DF8266    0FB64E 04       MOVZX ECX,BYTE PTR DS:[ESI+4]		; ecx = 0
00DF8532    8B0C8D 3687DE00 MOV ECX,DWORD PTR DS:[ECX*4+DE8736]      	; 0x90_5bi.00E1BC11
00DF87CF    3001            XOR BYTE PTR DS:[ECX],AL

000000char6_8(2) xor 47 (G)

00DF8A6F    83C6 05         ADD ESI,5					; esi = 00E1BBED
00DF8A72    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00DF8D16    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9F5
00DF8FFA    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 2
00DFDF5E    05 04EDFDAE     ADD EAX,AEFDED04

eax = 51021345
=> eax = 51021345 + AEFDED04 = 00000049

00DFE20E    0FB67E 06       MOVZX EDI,BYTE PTR DS:[ESI+6]		; edi = 3
00DFE4DC    8904BD 3687DE00 MOV DWORD PTR DS:[EDI*4+DE8736],EAX		; set 00000049 in memory
00DFE4E3    83C6 07         ADD ESI,7					; esi = 00E1BBF4
00DFE7A5    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 0
00DFEA74    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9A9
00DFED0E    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]
00DEC633    8B46 02         MOV EAX,DWORD PTR DS:[ESI+2]		; eax = 5311A8F3
00DEC8CD    05 3713D0AD     ADD EAX,ADD01337				; eax = 00E1BC2A
00DECB8A    50              PUSH EAX                                 	; 0x90_5bi.00E1BC2A
00DECE37    B8 D1F5FFFF     MOV EAX,-0A2F
00DED113    F7D0            NOT EAX					; eax = 00000A2E
00DED3BB    35 280A0000     XOR EAX,0A28				; eax = 6
00DED680    8D3406          LEA ESI,DWORD PTR DS:[ESI+EAX]		; esi = 00E1BBFA
00DED936    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 0
00DEDC00    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9A9
00DEDE7F    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 3
00E1B372    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]
00E1B376    83F0 66         XOR EAX,66					; eax = 0
00E1B64A    8F0485 3687DE00 POP DWORD PTR DS:[EAX*4+DE8736]          	; 0x90_5bi.00E1BC2A
00E1B8CF    83C6 04         ADD ESI,4
00E1B8D2    4E              DEC ESI					; esi = 00E1BBFD
00E1B8D3    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00E1B8D6    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9F5		
00E1B8DD    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 4
00E0D76F    FF0485 3687DE00 INC DWORD PTR DS:[EAX*4+DE8736]		; 000000char6_8(2) + 1

000000char6_8(3) =  000000char6_8(2) + 1

00E0D776    0F85 76050000   JNZ 0x90_5bi.00E0DCF2
00E0DF7A    C705 4A87DE00 0>MOV DWORD PTR DS:[DE874A],1
00E0E229    83C6 03         ADD ESI,3					; esi = 00E1BC00
00E0E4FA    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 1
00E0E7C1    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9BD
00E0E7C8    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 3
00DF7787    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 2
00DF7A49    8B0485 3687DE00 MOV EAX,DWORD PTR DS:[EAX*4+DE8736]		; eax = 000000char6_8(3)
00DF7CF9    0FB64E 03       MOVZX ECX,BYTE PTR DS:[ESI+3]		; ecx = 0
00DF8266    0FB64E 04       MOVZX ECX,BYTE PTR DS:[ESI+4]		; ecx = 0
00DF8532    8B0C8D 3687DE00 MOV ECX,DWORD PTR DS:[ECX*4+DE8736]      	; 0x90_5bi.00E1BC2A
00DF87CF    3001            XOR BYTE PTR DS:[ECX],AL			; xor 0x43 and 0x14

An other decryption loop is at the end of the code of the VM.
The hardware breakpoints used to decrypt it quickly are set at :

00E0E7D2
00E0B5A3
00E09A71
00DF9004
(The sames than before).

This decryption loop will decrypt a string and we can see that the last byte of the string to decrypt is 0x43.

00E1BC1E                                      14 26 2F 20
00E1BC2E  2C 2E 26 6D 6D 6D 49 4E 06 3B 33 2F 2C 2A 37 63
00E1BC3E  25 2C 31 63 2A 37 63 27 2C 26 30 2D 64 37 63 2E
00E1BC4E  22 37 37 26 31 63 72 6D 3B 63 00 2C 36 31 37 26
00E1BC5E  30 3A 63 2C 25 63 0D 2A 20 2C 2F 22 30 63 01 31
00E1BC6E  36 2F 26 39 43 

So if we want to correctly decrypt the string, the value to xor with will be 0x43, and we will have an end of string (0).

000000char6_8(3) xor 14  -> 000000char6_8(3) needs to be equal to 0x43 to correctly decrypt the string.

So we have :
000000char6_8(3) = 0x43
<=> 000000char6_8(2) = 0x43 - 1 = 0x42
<=> 000000char6_8(1) = 0x42 + 0x4E = 0x90
<=> 000000char6_8 = 0x90 - 1 = 0x8F
<=> 000000char6 + 000000char8 = 0x8F

And the possible values for char6 and char8 are :

! and n
" and m
# and l
$ and k
% and j
& and i
' and h
( and g
) and f
* and e
+ and d
, and c
- and b
. and a
/ and `
0 and _
1 and ^
2 and ]
3 and \
4 and [
5 and Z
6 and Y
7 and X
8 and W
9 and V
: and U
; and T
< and S
= and R
> and Q
? and P
@ and O
A and N
B and M
C and L
D and K
E and J
F and I
G and H

When the string is decrypted, we can read :

00E1BC24                    57 65 6C 63 6F 6D 65 2E 2E 2E        Welcome...
00E1BC34  0A 0D 45 78 70 6C 6F 69 74 20 66 6F 72 20 69 74  ..Exploit for it
00E1BC44  20 64 6F 65 73 6E 27 74 20 6D 61 74 74 65 72 20   doesn't matter
00E1BC54  31 2E 78 20 43 6F 75 72 74 65 73 79 20 6F 66 20  1.x Courtesy of
00E1BC64  4E 69 63 6F 6C 61 73 20 42 72 75 6C 65 7A 00     Nicolas Brulez.

Now we will try to show this string in the console.

00E0E4FA    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 2
00E0E7C1    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1B9F5
00E0E7C8    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 3
00E09D76    0FB646 02       MOVZX EAX,BYTE PTR DS:[ESI+2]		; eax = 3
00E0A03E    FF0C85 3687DE00 DEC DWORD PTR DS:[EAX*4+DE8736]		; 1 - 0 (fin décryption)
00E0A045    0F85 C6070000   JNZ 0x90_5bi.00E0A811
00E0A2E4    8325 4A87DE00 0>AND DWORD PTR DS:[DE874A],0			; value of the mark AND 0
00E0AD8F    83C6 03         ADD ESI,3					; esi = 00E1BC0B 
00E0B06B    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 4
00E0B31E    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1BA29
00E0B599    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 1
00E07C49    A1 4A87DE00     MOV EAX,DWORD PTR DS:[DE874A]		; eax = value of the mark (0)
00E07EF4    85C0            TEST EAX,EAX				; test the mark
00E07EF6    0F85 550B0000   JNZ 0x90_5bi.00E08A51			; no jump
00E081AF    83C6 06         ADD ESI,6					; esi = 00E1BC11
00E08458    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 5
00E08734    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E1BA35
00E0873B    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 1
00E1555E    5E              POP ESI                                  	; 0x90_5bi.00E1BB54

00E1BB54  13 73                                            .s		
; the result of the char6_char5 value xored with 4247 before

00E1555F    0FB606          MOVZX EAX,BYTE PTR DS:[ESI]			; eax = 13
00E15811    8B3C85 91B9E100 MOV EDI,DWORD PTR DS:[EAX*4+E1B991]      	; 0x90_5bi.00E016ED
00E15AC3    0FB646 01       MOVZX EAX,BYTE PTR DS:[ESI+1]		; eax = 73

We are in a SEH here, and with sadness we can see that it crashes when the execute the sysenter...

7FFE0300    8BD4            MOV EDX,ESP
7FFE0302    0F34            SYSENTER					; <--- here
7FFE0304    C3              RETN

Before executing this code, it gets the "1373" value (the result of the operation : char6 xor 42 and char5 xor 47).
I decided to select 0 as a result, maybe it will not crash anymore...
The unique way to have char6 xor 42 = 0 and char5 xor 47 = 0 is :

5eme char xor 47 (G) = 0
<=> 5eme char = 47 (G)

6eme char xor 42 (B)
<=> 6eme char = 42 (B)

If we read the tables I wrote above, we can see :

"The possible values for char5 and char7 are :
(000000char5 + 000000char7) = 000000A8
[...]
G and a
[...]"
So if char5 = "G", char7 will be "a"

"And the possible values for char6 and char8 are :
[...]
B and M
[...]"
So if char6 = "B", char7 will be "M"

=> A correct pass will be for example :
"1D3NGBaM" (without double-quote)

We test it :

C:\agadou>0x90.exe 1D3NGBaM
Welcome...
Exploit for it doesn't matter 1.x Courtesy of Nicolas Brulez
C:\agadou>

It seems to be perfect :) Yaooh !

The other valid passwords found with the previous tables above and by testing in a cmd : 
1D3NGAaN
1D3NGCaL
1D3NCCeL
1D3NDBdM
1D3NEAcN
1D3NEGcH

What techniques or methods can you think of that would make the binary harder to reverse engineer ?

The binary is ever hard to reverse engineer ! But as we have seen, I was able to quickly trace the code because there are some vulnerabilies in the protection.
I think obfuscation code between the real instructions of the VM would be better.
Find a solution to disallow BPMs on the SEH handler would be a problem (boring!), and more layers too... there are never enough layers ;)
Add some CRC checks to verify the integrity of the binary : if the obfuscation code are cleared that will be detected.
Maybe add a anti-dump trick : no errors allowed in a manual analyse.
And a system of authentification harder to reverse with tests on the MD5 hash of the password for instance... not directly on the value.
In my opinion, the protection is too much repetitive. Automatisation the decryption of the layers is not easy, but we can suppose these layers were generated with a tool. The code is the same each time or nearly the same.
It is the same problem for the SEH and the detection by exceptions for example. If we understand one of these and we pass succesfully one of these, then we are able to pass all of them... we just need to be patient. It's a shame :)

Thanks and greetings

Thanks to Nicolas Brulez and The Honeynet Project for this very interesting binary.
Thanks to my friends for motivation and to readers of this paper for their tolerance... I know, I have to improve my english language...
Greetings to all my french friends.


E. Grandjean (e.grandjean at no-log.org)