Write-ups/pwnable.xyz

xor - pwnable.xyz

dolphinlmg 2020. 2. 11. 23:45

Prob Info

 

Checksec

 

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  int v3; // [rsp+Ch] [rbp-24h]
  __int64 v4; // [rsp+10h] [rbp-20h]
  __int64 v5; // [rsp+18h] [rbp-18h]
  __int64 v6; // [rsp+20h] [rbp-10h]
  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);
}

숫자 세개를 입력받는데 모두 0이 아니고 v6는 9보다 커야한다.

 

.text:0000000000000AB3                 mov     rax, [rbp+var_10]
.text:0000000000000AB7                 cmp     rax, 9
.text:0000000000000ABB                 jg      short loc_AC3

v6가 음수여도 조건문을 통과할 수 있다. 그렇게 되면 result보다 아래에 있는 영역에 접근 할 수 있는데, Full RELRO와 PIE가 걸려있어 GOT Overwrite도 불가능하다. 일단 gdb에서 vmmap을 확인해 봤다.

 

pwndbg> vmmap
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
    0x555555554000     0x555555555000 rwxp     1000 0      /home/dpster/Desktop/Pwnable/pwnable_xyz/xor/image/challenge/challenge
    0x555555755000     0x555555756000 r--p     1000 1000   /home/dpster/Desktop/Pwnable/pwnable_xyz/xor/image/challenge/challenge
    0x555555756000     0x555555757000 rw-p     1000 2000   /home/dpster/Desktop/Pwnable/pwnable_xyz/xor/image/challenge/challenge
    0x555555757000     0x555555778000 rw-p    21000 0      [heap]
    0x7ffff7a0d000     0x7ffff7bcd000 r-xp   1c0000 0      /lib/x86_64-linux-gnu/libc-2.23.so
    0x7ffff7bcd000     0x7ffff7dcd000 ---p   200000 1c0000 /lib/x86_64-linux-gnu/libc-2.23.so
    0x7ffff7dcd000     0x7ffff7dd1000 r--p     4000 1c0000 /lib/x86_64-linux-gnu/libc-2.23.so
    0x7ffff7dd1000     0x7ffff7dd3000 rw-p     2000 1c4000 /lib/x86_64-linux-gnu/libc-2.23.so
    0x7ffff7dd3000     0x7ffff7dd7000 rw-p     4000 0
    0x7ffff7dd7000     0x7ffff7dfd000 r-xp    26000 0      /lib/x86_64-linux-gnu/ld-2.23.so
    0x7ffff7fdd000     0x7ffff7fe0000 rw-p     3000 0
    0x7ffff7ff7000     0x7ffff7ffa000 r--p     3000 0      [vvar]
    0x7ffff7ffa000     0x7ffff7ffc000 r-xp     2000 0      [vdso]
    0x7ffff7ffc000     0x7ffff7ffd000 r--p     1000 25000  /lib/x86_64-linux-gnu/ld-2.23.so
    0x7ffff7ffd000     0x7ffff7ffe000 rw-p     1000 26000  /lib/x86_64-linux-gnu/ld-2.23.so
    0x7ffff7ffe000     0x7ffff7fff000 rw-p     1000 0
    0x7ffffffde000     0x7ffffffff000 rw-p    21000 0      [stack]
0xffffffffff600000 0xffffffffff601000 r-xp     1000 0      [vsyscall]

특이하게 code영역에 w 권한을 줘서 쓰기가 가능하다. 일단 PIE가 걸려있어도 offset은 같기 때문에 code영역에 접근해 수정을 할 수 있다.

 

.bss:0000000000202200 ; _QWORD result[10]
.bss:0000000000202200 result          dq 0Ah dup(?)           ; DATA XREF: main+B0↑o
.bss:0000000000202200                                         ; main+C7↑o
.text:0000000000000AC3                 mov     edi, 1          ; status
.text:0000000000000AC8                 call    exit

이 부분을 수정할 것이다. 헥스로 보면 아래와 같다.

 

E8 63 FD FF FF

call의 opcode는 오프셋을 구해서 만들 수 있다.

E8 54 FF FF FF

저 위치에서 win을 호출하기 위한 opcode이다. 이를 0xAC8에 적어주면 된다.

 

Reference


https://umbum.tistory.com/102