2021. 2. 15. 18:56ㆍFTZ
[ Level 16 ]
level16 로그인
ID : level16
PW : about to cause mass
힌트를 보니 attackme.c 파일의 소스코드가 나온 것 같다.
level16에서는 main함수 외에도 함수가 있으며, 함수 포인터가 사용되었다.
※ 함수 포인터란? 특정 함수에 대한 메모리 주소를 담을 수 있는 것 <형태> [반환값자료형](*함수포인터이름)(); ex) void (*fp)(); // 반환값과 매개변수가 없는 함수 포인터 fp 선언 |
힌트에 있는 void (*call)()=printit;은 printit 함수의 메모리 주소를 함수 포인터 fp에 저장한 것과 같다.
따라서 이후에 call()을 사용하게 되면 printit함수가 실행된다.
이번 문제는 Buffer Overflow을 이용하여 printit함수가 아닌 shell함수를 call에 저장하여 실행하도록 하면 될 것 같다.
attackme를 gdb로 실행시키고 intel문법으로 바꿔준 후, main함수를 어셈블리 코드로 확인한다.
main 함수를 보면 변수 crap과 함수 포인터 call, 배열 buf를 선언하기 위해 0x38의 공간을 만들어 주었다.
( 56byte의 공간이 만들어진 것이다. )
다음으로 [ebp-16]에 0x8048500을 대입하는 것을 볼 수 있다.
x명령어를 사용하여 0x8048500의 값이 무엇인지 확인해보니 printit함수인 것을 볼 수 있다.
따라서 [ebp-16]은 call 함수 포인터인 것을 알 수 있다.
그리고 아래의 fgets함수에 들어갈 매개변수 중 ds:0x80496e8(stdin), 0x30(48), [ebp-56] 순으로 push하는 것을 보니
[ebp-56]가 buf라는 것도 알 수 있다.
buf와 call 사이의 40byte만큼의 공간이 있다는 사실을 알게 되었다!
disass printit을 입력하여 printit 함수도 어셈블리 코드로 확인해 보니,
0x8048500는 printit함수의 시작 주소인 것을 확인할 수 있었다.
그렇다면 shell함수의 시작 주소를 찾아내어 함수 포인터인 call에 대입하게 되면, main에서 call함수를 호출할 때
printit함수가 아닌 shell함수가 호출될 것이다.
이제 disass shell을 입력하여 shell함수의 시작 주소를 확인한다.
shell함수의 시작 주소가 0x080484d0인 것을 알아내었다.
buf와 call까지 40byte의 공간이 있으므로 \x90을 40byte만큼 입력해주고,
이후에 shell함수의 시작 주소를 입력하여 실행하면 될 것이다.
실행한 뒤 my-pass를 입력해주면 level17의 Password를 알 수 있다!
[ Level 16 Clear ]
'FTZ' 카테고리의 다른 글
[FTZ] Level 18 (0) | 2021.02.23 |
---|---|
[FTZ] Level 17 (0) | 2021.02.15 |
[FTZ] Level 15 (0) | 2021.02.15 |
[FTZ] Level 14 (0) | 2021.02.15 |
[FTZ] Level 13 (0) | 2021.02.15 |