제리의 블로그

hacklu CTF 2018 Baby Reverse 본문

CTF/pwnable

hacklu CTF 2018 Baby Reverse

j3rrry 2018. 10. 16. 23:12
Baby Reverse (Category: Reverse)

Author(s): Staubfinger Solves: 63



요약

직접 어셈 단에서 짜서 컴파일한 바이너리가 제공된다.
printf(), scanf() 대신 syscall 을 이용한 SYS_write, SYS_read 가 사용되었다.

바이너리는 0x2e 만큼의 문자열을 입력받아서
XOR 연산 결과가
특정 테이블(0x40010C)과 같은지 비교하여 검증한다.

XOR 은 A ^ B = C 이면 A ^ C = B 이고 교환법칙이 성립한다.
어렵지않게 역연산을 해서 풀었다.



Difficulty: baby

Hey there!

Disclaimer: This chall is intended for new gamers only ;-)!
You veterans got plenty of other Challenges which will keep you busy, so please pass this Challenge to someone, who never or rarely reversed before!
We encourage everyone who never reversed anything to try this challenge.
We believe in you and your future reversing skills =).
You CAN do it!

The task is to find the correct input which will be the flag.
See the challenge files for more instructions.

Download

$ sha256sum *
3dfa78cf1c5ff85bf3bbbb94c2c8090105f88f0b7878d6e05e7a0a0ec1b1c384  chall
18f662b92ea63b94cb3f7b429ceb140d24fbf0605fe6b7e604a8ad7b67393b8d  notes
$ file *
chall:     ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped
notes:     ASCII text
$ checksec ./chall
[*] './chall'
    Arch:     amd64-64-little
    RELRO:    No RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x400080)
    RWX:      Has RWX segments
다운 받으면
실행 파일과 텍스트 파일을 받습니다.

$ ./chall
Welcome to this Chall!
Enter the Key to win:
Key 가 틀리면 바로 종료된다.

$ cat notes
Hey there, future Reverser!

We created this small challenge to introduce you to reversing. This task might _still_ take quite some time, but trust us, it will be very rewarding!
We sadly can't spoonfeed you, but we created a set of questions which you might want to answer yourself. We expect you to google on your own and find resources.

Sooo, lets get started!

- What kind of binary have you got infront of you? (Hint: "file" command)
- How can you disassemble the file? (objdump, gdb, radare...)
- Which programs are common debuggers?
- How can I use them? (we recommend gdb with the peda plugin)
- - how can I set breakpoints?
- - in which different ways can I step through programs?
- - how can I print/examine the content of memory/addresses
- what is inside registers? what's rax, rip, rsp?
- what is the linux syscall convention?
- - In which register is the second argument?
- - In which register is the syscall number?
- - - where can I find the syscall numbers on my own linux system?
- what happens at a call instruction?
- how can I compare strings in assembly?
- .. ask your teammates for more! annoy them if anything is unclear :P
- .. if you don't got any teammates, use IRC and say that it's about the baby challenge

There is a lot of work ahead of you, and maybe some sleepless nights with a lot of googling - but it will be worth it;-)!
We are certain that with a dedicated mind you can solve this task and from there on you'll be ready for a bright future!
Don't give up, we all have been there. Stick to it and you'll be rewarded =)
문제 접근하는 방법을 단계적으로 제시하고 있습니다.

.text:0000000000400080 ; =============== S U B R O U T I N E =======================================
.text:0000000000400080
.text:0000000000400080
.text:0000000000400080                 public start
.text:0000000000400080 start           proc near
.text:0000000000400080
.text:0000000000400080 ; FUNCTION CHUNK AT .text:00000000004000D2 SIZE 00000040 BYTES
.text:0000000000400080 ; FUNCTION CHUNK AT .text:000000000040011D SIZE 0000000A BYTES
.text:0000000000400080
.text:0000000000400080                 jmp     short loc_4000D2
.text:0000000000400080 start           endp ; sp-analysis failed
.text:0000000000400080
.text:0000000000400082
.text:0000000000400082 ; =============== S U B R O U T I N E =======================================
.text:0000000000400082
.text:0000000000400082
.text:0000000000400082 sub_400082      proc near               ; CODE XREF: start:loc_4000D2p
.text:0000000000400082                 xor     rax, rax
.text:0000000000400085                 inc     al              ; SYS_write
.text:0000000000400087                 xor     rdi, rdi
.text:000000000040008A                 inc     rdi             ; fd = 1 (stdout)
.text:000000000040008D                 pop     rsi             ; buf = 0x4000D7
.text:000000000040008E                 mov     dl, 2Eh         ; len = 0x2e
.text:0000000000400090                 syscall
.text:0000000000400092                 sub     al, 2Eh         ; SYS_read
.text:0000000000400094                 dec     edi             ; fd = 0 (stdin)
.text:0000000000400096                 syscall
.text:0000000000400098
.text:0000000000400098 encode:                                 ; CODE XREF: sub_400082+24j
.text:0000000000400098                 movzx   rdi, byte ptr [rsi+1]
.text:000000000040009D                 xor     [rsi], rdi      ; XOR encrypt
.text:00000000004000A0                 inc     rsi
.text:00000000004000A3                 dec     rdx             ; len = 0x2e
.text:00000000004000A6                 jnz     short encode
.text:00000000004000A8                 and     ecx, 2Eh
.text:00000000004000AB                 add     cl, 26h         ; rcx = loop counter = 0x2e
.text:00000000004000AE                 lea     rdi, [rsi+7]    ; rdi = 0x40010C
.text:00000000004000B2                 lea     rsi, [rdi-35h]  ; rsi = 0x4000D7
.text:00000000004000B6                 repe cmpsb              ; repe  = 같거나 loop counter 가 0 이 될 때까지 반복
.text:00000000004000B6                                         ; cmpsb = compare string byte
.text:00000000004000B6                                         ; http://faydoc.tripod.com/cpu/cmpsb.htm
.text:00000000004000B8                 test    rcx, rcx
.text:00000000004000BB                 jnz     short exit
.text:00000000004000BD                 xor     al, 2Fh
.text:00000000004000BF                 push    21796159h       ; 0x21796159 = "Yay!"
.text:00000000004000C4                 mov     rsi, rsp
.text:00000000004000C7                 mov     dl, 4
.text:00000000004000C9                 mov     edi, 1
.text:00000000004000CE                 syscall
.text:00000000004000D0                 jmp     short exit
.text:00000000004000D0 sub_400082      endp ; sp-analysis failed
.text:00000000004000D0
.text:00000000004000D2 ; ---------------------------------------------------------------------------
.text:00000000004000D2 ; START OF FUNCTION CHUNK FOR start
.text:00000000004000D2
.text:00000000004000D2 loc_4000D2:                             ; CODE XREF: startj
.text:00000000004000D2                 call    sub_400082
.text:00000000004000D2 ; ---------------------------------------------------------------------------
.text:00000000004000D7 aWelcomeToThisC db 'Welcome to this Chall! ',0Ah
.text:00000000004000D7                 db 'Enter the Key to win: ',0
.text:0000000000400106 ; ---------------------------------------------------------------------------
.text:0000000000400106
.text:0000000000400106 exit:                                   ; CODE XREF: sub_400082+39j
.text:0000000000400106                                         ; sub_400082+4Ej
.text:0000000000400106                 xor     eax, eax
.text:0000000000400108                 mov     al, SYS_exit
.text:000000000040010A                 syscall
.text:000000000040010A ; ---------------------------------------------------------------------------
.text:000000000040010C                 db  0Ah
.text:000000000040010D                 db  0Dh
.text:000000000040010E                 db    6
.text:000000000040010F                 db  1Ch
.text:0000000000400110                 db  22h ; "
.text:0000000000400111                 db  38h ; 8
.text:0000000000400111 ; END OF FUNCTION CHUNK FOR start
.text:0000000000400112                 db  18h
.text:0000000000400113                 db  26h ; &
.text:0000000000400114                 db  36h ; 6
.text:0000000000400115                 db  0Fh
.text:0000000000400116                 db  39h ; 9
.text:0000000000400117                 db  2Bh ; +
.text:0000000000400118                 db  1Ch
.text:0000000000400119                 db  59h ; Y
.text:000000000040011A                 db  42h ; B
.text:000000000040011B                 db  2Ch ; ,
.text:000000000040011C                 db  36h ; 6
.text:000000000040011D ; START OF FUNCTION CHUNK FOR start
.text:000000000040011D                 db  1Ah
.text:000000000040011E                 db  2Ch ; ,
.text:000000000040011F                 db  26h ; &
.text:0000000000400120                 db  1Ch
.text:0000000000400121                 db  17h
.text:0000000000400122                 db  2Dh ; -
.text:0000000000400123                 db  39h ; 9
.text:0000000000400124                 db  57h ; W
.text:0000000000400125                 db  43h ; C
.text:0000000000400126                 db    1
.text:0000000000400126 ; END OF FUNCTION CHUNK FOR start
.text:0000000000400127                 db    7
.text:0000000000400128                 db  2Bh ; +
.text:0000000000400129                 db  38h ; 8
.text:000000000040012A                 db    9
.text:000000000040012B                 db    7
.text:000000000040012C                 db  1Ah
.text:000000000040012D                 db    1
.text:000000000040012E                 db  17h
.text:000000000040012F                 db  13h
.text:0000000000400130                 db  13h
.text:0000000000400131                 db  17h
.text:0000000000400132                 db  2Dh ; -
.text:0000000000400133                 db  39h ; 9
.text:0000000000400134                 db  0Ah
.text:0000000000400135                 db  0Dh
.text:0000000000400136                 db    6
.text:0000000000400137                 db  46h ; F
.text:0000000000400138                 db  5Ch ; \
.text:0000000000400139                 db  7Dh ; }
.text:0000000000400139 _text           ends
.text:0000000000400139
.text:0000000000400139
.text:0000000000400139                 end start
0x4000B6 의 repe cmpsb 는 strncmp 와 비슷하다.
rdi 와 rsi 를 비교하고
rcx 가 길이
strncmp(0x40010C, 0x4000D7, 0x2e);


000000000040010C  0A 0D 06 1C 22 38 18 26  36 0F 39 2B 1C 59 42 2C  ...."8.&6.9+.YB,
000000000040011C  36 1A 2C 26 1C 17 2D 39  57 43 01 07 2B 38 09 07  6.,&..-9WC..+8..
000000000040012C  1A 01 17 13 13 17 2D 39  0A 0D 06 46 5C 7D        ......-9...F\}


from pwn import *

goal = '''0A 0D 06 1C 22 38 18 26  36 0F 39 2B 1C 59 42 2C
36 1A 2C 26 1C 17 2D 39  57 43 01 07 2B 38 09 07
1A 01 17 13 13 17 2D 39  0A 0D 06 46 5C 7D      '''.split()
goal = map(lambda x: int(x, 16), goal)

tmp = goal[-1]
flag = chr(tmp)

for i in range(len(goal) - 1, 0, -1):
    tmp ^= goal[i - 1]
    flag = chr(tmp) + flag

print flag
# flag{Yay_if_th1s_is_yer_f1rst_gnisrever_flag!}


$ ./chall
Welcome to this Chall!
Enter the Key to win: flag{Yay_if_th1s_is_yer_f1rst_gnisrever_flag!}
Yay!


Comments