0xd13a

A rookie in a world of pwns

FLARE-ON 2017 Writeup: IgniteMe.exe

This is another simple challenge. When run, it prompts for a password and verifies it:

1
2
3
C:\work\flareon17>IgniteMe.exe
G1v3 m3 t3h fl4g:  test
N0t t00 h0t R we? 7ry 4ga1nz plzzz!

Quick analysis in IDA Pro shows that the “meat” of password decoding logic is in sub_401050:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
.text:00401050 sub_401050      proc near               ; CODE XREF: start+44
.text:00401050
.text:00401050 varFlagSize     = dword ptr -0Ch
.text:00401050 varLoopCounter  = dword ptr -8
.text:00401050 varEncodingFactor= byte ptr -1
.text:00401050
.text:00401050                 push    ebp
.text:00401051                 mov     ebp, esp
.text:00401053                 sub     esp, 0Ch
.text:00401056                 push    offset byte_403078
.text:0040105B                 call    sub_401020      ; determine encoded flag size and put it in varFlagSize
.text:00401060                 add     esp, 4
.text:00401063                 mov     [ebp+varFlagSize], eax
.text:00401066                 call    sub_401000      ; calculate initial encoding factor
.text:0040106B                 mov     [ebp+varEncodingFactor], al
.text:0040106E                 mov     eax, [ebp+varFlagSize]
.text:00401071                 sub     eax, 1
.text:00401074                 mov     [ebp+varLoopCounter], eax
.text:00401077                 jmp     short loc_401082
.text:00401079 ; ---------------------------------------------------------------------------
.text:00401079
.text:00401079 loc_401079:                             ; CODE XREF: sub_401050+5D
.text:00401079                 mov     ecx, [ebp+varLoopCounter]
.text:0040107C                 sub     ecx, 1
.text:0040107F                 mov     [ebp+varLoopCounter], ecx
.text:00401082
.text:00401082 loc_401082:                             ; CODE XREF: sub_401050+27
.text:00401082                 cmp     [ebp+varLoopCounter], 0 ; run through input string
.text:00401086                 jl      short loc_4010AF
.text:00401088                 mov     edx, [ebp+varLoopCounter]
.text:0040108B                 movsx   eax, byte_403078[edx]
.text:00401092                 movzx   ecx, [ebp+varEncodingFactor]
.text:00401096                 xor     eax, ecx        ; encode one character by XORing it with factor
.text:00401098                 mov     edx, [ebp+varLoopCounter]
.text:0040109B                 mov     byte_403180[edx], al
.text:004010A1                 mov     eax, [ebp+varLoopCounter]
.text:004010A4                 mov     cl, byte_403078[eax]
.text:004010AA                 mov     [ebp+varEncodingFactor], cl ; set the factor to the encoded character value
.text:004010AD                 jmp     short loc_401079
.text:004010AF ; ---------------------------------------------------------------------------
.text:004010AF
.text:004010AF loc_4010AF:                             ; CODE XREF: sub_401050+36
.text:004010AF                 mov     [ebp+varLoopCounter], 0
.text:004010B6                 jmp     short loc_4010C1
.text:004010B8 ; ---------------------------------------------------------------------------
.text:004010B8
.text:004010B8 loc_4010B8:                             ; CODE XREF: sub_401050:loc_4010E3
.text:004010B8                 mov     edx, [ebp+varLoopCounter]
.text:004010BB                 add     edx, 1
.text:004010BE                 mov     [ebp+varLoopCounter], edx
.text:004010C1
.text:004010C1 loc_4010C1:                             ; CODE XREF: sub_401050+66
.text:004010C1                 cmp     [ebp+varLoopCounter], 27h
.text:004010C5                 jnb     short loc_4010E5
.text:004010C7                 mov     eax, [ebp+varLoopCounter]
.text:004010CA                 movsx   ecx, byte_403180[eax]
.text:004010D1                 mov     edx, [ebp+varLoopCounter]
.text:004010D4                 movzx   eax, byte_403000[edx]
.text:004010DB                 cmp     ecx, eax        ; compare each string character with corresponding character in encoded flag
.text:004010DD                 jz      short loc_4010E3
.text:004010DF                 xor     eax, eax        ; if character does not match exit with error
.text:004010E1                 jmp     short loc_4010EA
.text:004010E3 ; ---------------------------------------------------------------------------
.text:004010E3
.text:004010E3 loc_4010E3:                             ; CODE XREF: sub_401050+8D
.text:004010E3                 jmp     short loc_4010B8
.text:004010E5 ; ---------------------------------------------------------------------------
.text:004010E5
.text:004010E5 loc_4010E5:                             ; CODE XREF: sub_401050+75
.text:004010E5                 mov     eax, 1
.text:004010EA
.text:004010EA loc_4010EA:                             ; CODE XREF: sub_401050+91
.text:004010EA                 mov     esp, ebp
.text:004010EC                 pop     ebp
.text:004010ED                 retn
.text:004010ED sub_401050      endp

Let’s replicate the algorithm in Python:

1
2
3
4
5
6
7
8
9
10
11
data = bytearray(open("IgniteMe.exe","rb").read())[0xa00:0xa00+0x27]

out = ""

factor = 4 # (rol(0x80070057 & 0xffff0000,4) >> 1) & 0xFF

for x in range(len(data)):
	factor = data[len(data)-x-1] ^ factor
	out += chr(factor)
	
print out[::-1]

Running the script gets us the flag:

1
2
C:\work\flareon17>\Python27\python.exe ignite_solve.py
R_y0u_H0t_3n0ugH_t0_1gn1t3@flare-on.com