I tried out Debug Fundamentals Exercise 4: The GAMEOVER exercise on GES Blog. I did not make all right, especially the reverse engineering part. After spending some time on the assembly code of functions in the exercise, I list below their annotated assembly. It contains some interesting instructions for string manipulation.
0:000> uf dbgex4!main
dbgex4!main [c:\tmp\dbgex4.cpp @ 119]:
119 00ac12c1 mov edi,edi
119 00ac12c3 push ebp
119 00ac12c4 mov ebp,esp
119 00ac12c6 sub esp,4Ch ; allocate buffer[4C] on the stack
121 00ac12c9 lea eax,[ebp-4Ch] ; store it in EAX
121 00ac12cc push eax ; pass the buffer in callee
121 00ac12cd call dbgex4!snap (00ac1292)
122 00ac12d2 leave
122 00ac12d3 ret
0:000> uf dbgex4!snap
dbgex4!crack [c:\tmp\dbgex4.cpp @ 67]:
67 00ac1245 mov edi,edi
67 00ac1247 push ebp
67 00ac1248 mov ebp,esp
68 00ac124a mov ecx,dword ptr [ebp+8] ; store passed in buffer in ECX
71 00ac124d cmp byte ptr [ecx],0 ; check if it is empty
71 00ac1250 push esi
71 00ac1251 mov esi,ecx
71 00ac1253 mov eax,ecx
71 00ac1255 je dbgex4!crack+0x18 (00ac125d)
dbgex4!crack+0x12 [c:\tmp\dbgex4.cpp @ 71]:
71 00ac1257 inc eax
71 00ac1258 cmp byte ptr [eax],0
71 00ac125b jne dbgex4!crack+0x12 (00ac1257) ; the above three instructions move EAX to the NULL char
dbgex4!crack+0x18 [c:\tmp\dbgex4.cpp @ 72]:
72 00ac125d dec eax
74 00ac125e cmp eax,ecx
74 00ac1260 jbe dbgex4!crack+0x2d (00ac1272) ; the above three instructions move EAX one step back to the last non-NULL char
dbgex4!crack+0x1d [c:\tmp\dbgex4.cpp @ 74]:
74 00ac1262 push ebx
dbgex4!crack+0x1e [c:\tmp\dbgex4.cpp @ 77]:
77 00ac1263 mov bl,byte ptr [eax]
77 00ac1265 mov dl,byte ptr [esi]
77 00ac1267 mov byte ptr [esi],bl
77 00ac1269 inc esi
78 00ac126a mov byte ptr [eax],dl
78 00ac126c dec eax
78 00ac126d cmp eax,esi
78 00ac126f ja dbgex4!crack+0x1e (00ac1263) ; reverse the content of string
dbgex4!crack+0x2c [c:\tmp\dbgex4.cpp @ 78]:
78 00ac1271 pop ebx
dbgex4!crack+0x2d [c:\tmp\dbgex4.cpp @ 83]:
83 00ac1272 xor eax,eax ; zero out EAX
85 00ac1274 cmp byte ptr [ecx],0C3h ; check if the first char is 0C3
85 00ac1277 pop esi
85 00ac1278 je dbgex4!crack+0x3c (00ac1281)
dbgex4!crack+0x35 [c:\tmp\dbgex4.cpp @ 88]:
88 00ac127a inc eax
88 00ac127b cmp byte ptr [eax+ecx],0C3h
88 00ac127f jne dbgex4!crack+0x35 (00ac127a) ; the above three instructions search for 0C3 in the string. EXA stores the index of char -- 0C3. If there is no 0C3 in the string, the code is in trouble.
dbgex4!crack+0x3c [c:\tmp\dbgex4.cpp @ 91]:
91 00ac1281 inc eax ; turn the index into length
93 00ac1282 push eax
93 00ac1283 push ecx
93 00ac1284 call dbgex4!pop (00ac1216)
94 00ac1289 pop ebp
94 00ac128a ret 4
dbgex4!snap [c:\tmp\dbgex4.cpp @ 103]:
103 00ac1292 mov edi,edi
103 00ac1294 push ebp
103 00ac1295 mov ebp,esp
104 00ac1297 mov al,byte ptr [dbgex4!string (00ac3000)] ; al stores first char
104 00ac129c test al,al ; check if the string @ 00ac3000 is empty
104 00ac129e je dbgex4!snap+0x24 (00ac12b6)
dbgex4!snap+0xe [c:\tmp\dbgex4.cpp @ 104]:
104 00ac12a0 mov edx,dword ptr [ebp+8] ; edx stores destination buffer
104 00ac12a3 mov cl,al ; cl stores the first char
104 00ac12a5 mov eax,offset dbgex4!string (00ac3000) ; eax stores source buffer
104 00ac12aa sub edx,eax
dbgex4!snap+0x1a [c:\tmp\dbgex4.cpp @ 106]:
106 00ac12ac mov byte ptr [edx+eax],cl
106 00ac12af inc eax
106 00ac12b0 mov cl,byte ptr [eax]
106 00ac12b2 test cl,cl ; if cl = 0
106 00ac12b4 jne dbgex4!snap+0x1a (00ac12ac) ; the above six instructions copy data from source to desintation. The destination may not be NULL-terminated!
dbgex4!snap+0x24 [c:\tmp\dbgex4.cpp @ 110]:
110 00ac12b6 pop ebp
109 00ac12b7 jmp dbgex4!crack (00ac1245)
0:000> uf dbgex4!pop
dbgex4!pop [c:\tmp\dbgex4.cpp @ 49]:
49 00ac1216 mov edi,edi
49 00ac1218 push ebp
49 00ac1219 mov ebp,esp
51 00ac121b mov edx,dword ptr [ebp+0Ch] ; store the length
51 00ac121e push esi
51 00ac121f mov esi,dword ptr [ebp+8] ; store the buffer
53 00ac1222 mov al,byte ptr [esi+edx] ; store buffer[length]
53 00ac1225 mov ecx,esi
53 00ac1227 jmp dbgex4!pop+0x19 (00ac122f)
dbgex4!pop+0x13 [c:\tmp\dbgex4.cpp @ 54]:
54 00ac1229 mov byte ptr [ecx],al
54 00ac122b inc ecx
54 00ac122c mov al,byte ptr [ecx+edx]
dbgex4!pop+0x19 [c:\tmp\dbgex4.cpp @ 53]:
53 00ac122f test al,al
53 00ac1231 jne dbgex4!pop+0x13 (00ac1229) ; the above instructions move the content starting from length to the beginning of the string
dbgex4!pop+0x1d [c:\tmp\dbgex4.cpp @ 58]:
58 00ac1233 push esi
58 00ac1234 mov byte ptr [ecx],al ; set NULL-terminated
58 00ac1236 call dbgex4!boom (00ac11c5)
58 00ac123b pop esi
59 00ac123c pop ebp
59 00ac123d ret 8
0:000> uf dbgex4!boom
dbgex4!boom [c:\tmp\dbgex4.cpp @ 29]:
29 00ac11c5 mov edi,edi
29 00ac11c7 push ebp
29 00ac11c8 mov ebp,esp
33 00ac11ca mov eax,dword ptr [ebp+8]
33 00ac11cd mov cl,byte ptr [eax]
33 00ac11cf sub esp,2Ch ; reserve 2C on the stack
33 00ac11d2 test cl,cl
33 00ac11d4 je dbgex4!boom+0x20 (00ac11e5)
dbgex4!boom+0x11 [c:\tmp\dbgex4.cpp @ 33]:
33 00ac11d6 lea edx,[ebp-2Bh] ; set destination buffer with size of 2Bh
33 00ac11d9 sub edx,eax
dbgex4!boom+0x16 [c:\tmp\dbgex4.cpp @ 35]:
35 00ac11db mov byte ptr [edx+eax],cl
35 00ac11de inc eax
35 00ac11df mov cl,byte ptr [eax]
35 00ac11e1 test cl,cl ; if cl = 0
35 00ac11e3 jne dbgex4!boom+0x16 (00ac11db) ; the above instructions copy data from source (EAX) to desintation (EDX). If the source is larger than 2Bh, we have buffer overflow.
dbgex4!boom+0x20 [c:\tmp\dbgex4.cpp @ 38]:
38 00ac11e5 mov cl,byte ptr [ebp-2Ch]
38 00ac11e8 lea eax,[ebp-2Ch] ; set buffer with size of 2Ch
38 00ac11eb jmp dbgex4!boom+0x3f (00ac1204)
dbgex4!boom+0x28 [c:\tmp\dbgex4.cpp @ 38]:
38 00ac11ed mov cl,byte ptr [eax]
38 00ac11ef mov dl,byte ptr [eax]
38 00ac11f1 movzx ecx,cl ; convert to unsigned
38 00ac11f4 movzx edx,dl ; convert to unsigned
38 00ac11f7 shr ecx,4 ; ecx >>= 4
38 00ac11fa shl edx,4 ; edx <<= 4
38 00ac11fd or ecx,edx ; ecx |= edx
38 00ac11ff mov byte ptr [eax],cl ; store low 8 bits of ecx
38 00ac1201 inc eax
38 00ac1202 mov cl,byte ptr [eax]
dbgex4!boom+0x3f [c:\tmp\dbgex4.cpp @ 38]:
38 00ac1204 test cl,cl
38 00ac1206 jne dbgex4!boom+0x28 (00ac11ed) ; the above instructions switch the first four bits and the last four bits for each char in the string.
dbgex4!boom+0x43 [c:\tmp\dbgex4.cpp @ 40]:
40 00ac1208 mov eax,53454750h
41 00ac120d leave
41 00ac120e ret 4
Software Anti-Narrative
10 hours ago
0 comments:
Post a Comment