---
# System prepended metadata

title: HACKME CTF Writeup RE
tags: [Write-up, Reverse, CTF]

---

# HACKME CTF Writeup RE

###### tags: `CTF` `Write-up` `Reverse`

## 1. helloworld
- 先執行看看
![](https://i.imgur.com/8WPjEXC.png)
- 丟r2
:::info
1. 第23-29行push了一堆東西進stack,是後面用來decode出flag用的
2. 第39行: scanf('%d', ebp-0x10): 把輸入當成整數解析放進ebp-0x10 
i.e. ebp-0x10=int(input)
3. 第42行: 把int(input)跟0x12b9b0a1=314159265做比較,如果不相同就跳到(jne)Try hard
4. 第44行到第65行就是在做解析flag的動作
以ebp-0x30~ebp-0x14的內容為初始值,針對每個byte跟0x12b9b0a1做xor,並將該byte修改為xor後的結果,碰到0才停止(ebp-0x14就是00)
i.e. flag[i] = flag[i] ^ 0xa1
:::
```asm=
/ (fcn) main 223
|   main ();
|           ; var int local_2dh @ ebp-0x2d
|           ; var int local_29h @ ebp-0x29
|           ; var int local_25h @ ebp-0x25
|           ; var int local_21h @ ebp-0x21
|           ; var int local_1dh @ ebp-0x1d
|           ; var int local_19h @ ebp-0x19
|           ; var int local_15h @ ebp-0x15
|           ; var int local_11h @ ebp-0x11
|           ; var int local_10h @ ebp-0x10
|           ; var int local_ch @ ebp-0xc
|           ; var int local_4h_2 @ ebp-0x4
|           ; var int local_4h @ esp+0x4
|              ; DATA XREF from 0x08048387 (entry0)
|           0x0804846b      8d4c2404       lea ecx, dword [local_4h]   ; .//helloworld.c:4 ; 4
|           0x0804846f      83e4f0         and esp, 0xfffffff0
|           0x08048472      ff71fc         push dword [ecx - 4]
|           0x08048475      55             push ebp
|           0x08048476      89e5           mov ebp, esp
|           0x08048478      51             push ecx
|           0x08048479      83ec34         sub esp, 0x34               ; '4'
|           0x0804847c      c745d3f1e881.  mov dword [local_2dh], 0xc881e8f1 ; .//helloworld.c:6
|           0x08048483      c745d7d281cf.  mov dword [local_29h], 0xcecf81d2
|           0x0804848a      c745dbd581c0.  mov dword [local_25h], 0x81c081d5
|           0x08048491      c745dfd3c0d5.  mov dword [local_21h], 0xc8d5c0d3
|           0x08048498      c745e3cecfc0.  mov dword [local_1dh], 0xcdc0cfce
|           0x0804849f      c745e781cfd4.  mov dword [local_19h], 0xccd4cf81
|           0x080484a6      c745ebc3c4d3.  mov dword [local_15h], 0x8fd3c4c3
|           0x080484ad      c645ef00       mov byte [local_11h], 0
|           0x080484b1      83ec0c         sub esp, 0xc                ; .//helloworld.c:7
|           0x080484b4      68d0850408     push str.What_is_magic_number ; 0x80485d0 ; "What is magic number? "
|           0x080484b9      e862feffff     call sym.imp.printf         ; int printf(const char *format)
|           0x080484be      83c410         add esp, 0x10
|           0x080484c1      83ec08         sub esp, 8                  ; .//helloworld.c:8
|           0x080484c4      8d45f0         lea eax, dword [local_10h]
|           0x080484c7      50             push eax
|           0x080484c8      68e7850408     push 0x80485e7
|           0x080484cd      e87efeffff     call sym.imp.__isoc99_scanf
|           0x080484d2      83c410         add esp, 0x10
|           0x080484d5      8b45f0         mov eax, dword [local_10h]  ; .//helloworld.c:9
|           0x080484d8      3da1b0b912     cmp eax, 0x12b9b0a1
|       ,=< 0x080484dd      754e           jne 0x804852d
|       |   0x080484df      c745f4000000.  mov dword [local_ch], 0     ; .//helloworld.c:10
|      ,==< 0x080484e6      eb20           jmp 0x8048508
|      ||      ; JMP XREF from 0x08048515 (main)
|     .---> 0x080484e8      8d55d3         lea edx, dword [local_2dh]  ; .//helloworld.c:11
|     :||   0x080484eb      8b45f4         mov eax, dword [local_ch]
|     :||   0x080484ee      01d0           add eax, edx
|     :||   0x080484f0      0fb610         movzx edx, byte [eax]
|     :||   0x080484f3      8b45f0         mov eax, dword [local_10h]
|     :||   0x080484f6      89d1           mov ecx, edx
|     :||   0x080484f8      31c1           xor ecx, eax
|     :||   0x080484fa      8d55d3         lea edx, dword [local_2dh]
|     :||   0x080484fd      8b45f4         mov eax, dword [local_ch]
|     :||   0x08048500      01d0           add eax, edx
|     :||   0x08048502      8808           mov byte [eax], cl
|     :||   0x08048504      8345f401       add dword [local_ch], 1     ; .//helloworld.c:10
|     :||      ; JMP XREF from 0x080484e6 (main)
|     :`--> 0x08048508      8d55d3         lea edx, dword [local_2dh]
|     : |   0x0804850b      8b45f4         mov eax, dword [local_ch]
|     : |   0x0804850e      01d0           add eax, edx
|     : |   0x08048510      0fb600         movzx eax, byte [eax]
|     : |   0x08048513      84c0           test al, al
|     `===< 0x08048515      75d1           jne 0x80484e8
|       |   0x08048517      83ec08         sub esp, 8                  ; .//helloworld.c:13
|       |   0x0804851a      8d45d3         lea eax, dword [local_2dh]
|       |   0x0804851d      50             push eax
|       |   0x0804851e      68ea850408     push str.Flag_is_FLAG__s    ; 0x80485ea ; "Flag is FLAG{%s}\n"
|       |   0x08048523      e8f8fdffff     call sym.imp.printf         ; int printf(const char *format)
|       |   0x08048528      83c410         add esp, 0x10
|      ,==< 0x0804852b      eb10           jmp 0x804853d
|      ||      ; JMP XREF from 0x080484dd (main)
|      |`-> 0x0804852d      83ec0c         sub esp, 0xc                ; .//helloworld.c:15
|      |    0x08048530      68fc850408     push str.Try_Hard.          ; 0x80485fc ; "Try Hard."
|      |    0x08048535      e8f6fdffff     call sym.imp.puts           ; int puts(const char *s)
|      |    0x0804853a      83c410         add esp, 0x10
|      |       ; JMP XREF from 0x0804852b (main)
|      `--> 0x0804853d      b800000000     mov eax, 0                  ; .//helloworld.c:17
|           0x08048542      8b4dfc         mov ecx, dword [local_4h_2] ; .//helloworld.c:18
|           0x08048545      c9             leave
|           0x08048546      8d61fc         lea esp, dword [ecx - 4]
\           0x08048549      c3             ret
```
- 所以Magic Number就是314159265(0x12b9b0a1)
![](https://i.imgur.com/VHrtOq9.png)

## 2. simple
- 先執行看看
![](https://i.imgur.com/W51W14F.png)
- 丟r2
:::info
1. 第70行找到一個strcmp(ebp-0x8c, "UIJT.JT.ZPVS.GMBHUIJT.JT.ZPVS.GMBH")
2. 往回看發現ebp-0x8c是從edx來的,但中間過程有點複雜
:::
```asm=
|   main ();
|           ; var int local_8ch @ ebp-0x8c
|           ; var int local_4ch @ ebp-0x4c
|           ; var int local_ch @ ebp-0xc
|           ; var int local_4h_2 @ ebp-0x4
|           ; var int local_4h @ esp+0x4
|              ; DATA XREF from 0x080483c7 (entry0)
|           0x080484ab      8d4c2404       lea ecx, dword [local_4h]   ; .//simple-rev.c:7 ; 4
|           0x080484af      83e4f0         and esp, 0xfffffff0
|           0x080484b2      ff71fc         push dword [ecx - 4]
|           0x080484b5      55             push ebp                    ; .//-rev.c:201
|           0x080484b6      89e5           mov ebp, esp                ; .//-rev.c:293
|           0x080484b8      51             push ecx
|           0x080484b9      81ec94000000   sub esp, 0x94               ; .//-rev.c:363
|           0x080484bf      83ec0c         sub esp, 0xc                ; .//simple-rev.c:12
|           0x080484c2      6854860408     push 0x8048654
|           0x080484c7      e894feffff     call sym.imp.printf         ; int printf(const char *format)
|           0x080484cc      83c410         add esp, 0x10
|           0x080484cf      a1a0980408     mov eax, dword [obj.stdin]  ; .//simple-rev.c:13 ; [0x80498a0:4]=0
|           0x080484d4      83ec04         sub esp, 4
|           0x080484d7      50             push eax
|           0x080484d8      6a3f           push 0x3f                   ; '?' ; 63
|           0x080484da      8d45b4         lea eax, dword [local_4ch]
|           0x080484dd      50             push eax
|           0x080484de      e88dfeffff     call sym.imp.fgets          ; char *fgets(char *s, int size, FILE *stream)
|           0x080484e3      83c410         add esp, 0x10
|           0x080484e6      c745f4000000.  mov dword [local_ch], 0     ; .//simple-rev.c:15
|       ,=< 0x080484ed      eb4b           jmp 0x804853a
|       |      ; JMP XREF from 0x08048547 (main)
|      .--> 0x080484ef      8d55b4         lea edx, dword [local_4ch]  ; .//simple-rev.c:16
|      :|   0x080484f2      8b45f4         mov eax, dword [local_ch]
|      :|   0x080484f5      01d0           add eax, edx
|      :|   0x080484f7      0fb600         movzx eax, byte [eax]
|      :|   0x080484fa      3c0a           cmp al, 0xa                 ; 10
|     ,===< 0x080484fc      751b           jne 0x8048519
|     |:|   0x080484fe      8d55b4         lea edx, dword [local_4ch]  ; .//simple-rev.c:17
|     |:|   0x08048501      8b45f4         mov eax, dword [local_ch]
|     |:|   0x08048504      01d0           add eax, edx
|     |:|   0x08048506      c60000         mov byte [eax], 0
|     |:|   0x08048509      8d9574ffffff   lea edx, dword [local_8ch]  ; .//simple-rev.c:18
|     |:|   0x0804850f      8b45f4         mov eax, dword [local_ch]
|     |:|   0x08048512      01d0           add eax, edx
|     |:|   0x08048514      c60000         mov byte [eax], 0
|    ,====< 0x08048517      eb1d           jmp 0x8048536
|    ||:|      ; JMP XREF from 0x080484fc (main)
|    |`---> 0x08048519      8d55b4         lea edx, dword [local_4ch]  ; .//simple-rev.c:20
|    | :|   0x0804851c      8b45f4         mov eax, dword [local_ch]
|    | :|   0x0804851f      01d0           add eax, edx
|    | :|   0x08048521      0fb600         movzx eax, byte [eax]
|    | :|   0x08048524      83c001         add eax, 1
|    | :|   0x08048527      89c1           mov ecx, eax
|    | :|   0x08048529      8d9574ffffff   lea edx, dword [local_8ch]
|    | :|   0x0804852f      8b45f4         mov eax, dword [local_ch]
|    | :|   0x08048532      01d0           add eax, edx
|    | :|   0x08048534      8808           mov byte [eax], cl
|    | :|      ; JMP XREF from 0x08048517 (main)
|    `----> 0x08048536      8345f401       add dword [local_ch], 1     ; .//simple-rev.c:15
|      :|      ; JMP XREF from 0x080484ed (main)
|      :`-> 0x0804853a      8d55b4         lea edx, dword [local_4ch]
|      :    0x0804853d      8b45f4         mov eax, dword [local_ch]
|      :    0x08048540      01d0           add eax, edx
|      :    0x08048542      0fb600         movzx eax, byte [eax]
|      :    0x08048545      84c0           test al, al
|      `==< 0x08048547      75a6           jne 0x80484ef
|           0x08048549      b820860408     mov eax, str.UIJT.JT.ZPVS.GMBH ; .//simple-rev.c:24 ; 0x8048620 ; "UIJT.JT.ZPVS.GMBH"
|           0x0804854e      83ec08         sub esp, 8
|           0x08048551      50             push eax
|           0x08048552      8d8574ffffff   lea eax, dword [local_8ch]
|           0x08048558      50             push eax
|           0x08048559      e8f2fdffff     call sym.imp.strcmp         ; int strcmp(const char *s1, const char *s2)
|           0x0804855e      83c410         add esp, 0x10
|           0x08048561      85c0           test eax, eax
|       ,=< 0x08048563      7516           jne 0x804857b
|       |   0x08048565      83ec08         sub esp, 8                  ; .//simple-rev.c:25
|       |   0x08048568      8d45b4         lea eax, dword [local_4ch]
|       |   0x0804856b      50             push eax
|       |   0x0804856c      6863860408     push str.FLAG__s            ; 0x8048663 ; "FLAG{%s}\n"
|       |   0x08048571      e8eafdffff     call sym.imp.printf         ; int printf(const char *format)
|       |   0x08048576      83c410         add esp, 0x10
|      ,==< 0x08048579      eb10           jmp 0x804858b
|      ||      ; JMP XREF from 0x08048563 (main)
|      |`-> 0x0804857b      83ec0c         sub esp, 0xc                ; .//simple-rev.c:27
|      |    0x0804857e      686d860408     push str.Try_hard.          ; 0x804866d ; "Try hard."
|      |    0x08048583      e8f8fdffff     call sym.imp.puts           ; int puts(const char *s)
|      |    0x08048588      83c410         add esp, 0x10
|      |       ; JMP XREF from 0x08048579 (main)
|      `--> 0x0804858b      b800000000     mov eax, 0                  ; .//simple-rev.c:30
|           0x08048590      8b4dfc         mov ecx, dword [local_4h_2] ; .//simple-rev.c:31
|           0x08048593      c9             leave
|           0x08048594      8d61fc         lea esp, dword [ecx - 4]
\           0x08048597      c3             ret
```
- 猜測密碼可能跟"UIJT.JT.ZPVS.GMBH"有關,所以開gdb看看到底發生甚麼事
:::info
把斷點下在call strcmp的地方,密碼輸入"UIJT.JT.ZPVS.GMBH"
發現原來ebp-0x8c是放處理過後的輸入,可以看出規律是把輸入的字串的每個byte + 1
-> 從第50行的地方開始做,針對每個byte把+1之後的結果放在ecx,
- 然後第52-55行是把計算結果放進ebp-0x8c[i](i=>eax,初始為0)
- 第34行的作用就是讀到輸入的字串尾就不再進行上述動作
:::
![](https://i.imgur.com/mYtIGuY.png)

- 因此把"UIJT.JT.ZPVS.GMBH"都往前位移一次得到"THIS-IS-YOUR-FLAG"就是密碼惹
![](https://i.imgur.com/l1Yfua3.png)

## 3. passthis
- 是一個windows程式
![](https://i.imgur.com/PZeY8Gv.png)
- 丟IDA
1. shift+f12找字串
2. 重點Assembly
    :::info
    1. cmp al, 0Dh -> 這行應該是在判別字串尾
    2. cmp al, 'F' -> 判斷input[0]是不是'F'
        如果是就把edx清成0(xor edx, edx)
        接著把edx當index使用
        比較input[i] ^ byte_404040[i]的結果是否=0x87
    3. 整個字串都比較完之後, bt ecx, eax
        此時eax應該=0xa(字串尾)
        這個指令會把ecx的第eax個bit放進CarryFlag中
        jnb(jump if not below => 大於等於跳 => CF=0跳)
        這邊CF=1所以不跳 => put('Good Flag')
    :::
    ![](https://i.imgur.com/qnDfBzo.png)
- 用byte_404040的內容來寫個python script
(Note: 選取想要的內容後按shif+E就可以自動生成想要使用的資料格式)
![](https://i.imgur.com/1aOH9KS.png)
    - python script
    ```python= 
    byte404040 =  [0xC1, 0xCB, 0xC6, 0xC0, 0xFC, 0xC9, 0xE8, 0xAB, 0xA7, 0xDE, 
      0xE8, 0xF2, 0xA7, 0xF4, 0xEF, 0xE8, 0xF2, 0xEB, 0xE3, 0xA7, 
      0xE9, 0xE8, 0xF3, 0xA7, 0xF7, 0xE6, 0xF4, 0xF4, 0xA7, 0xF3, 
      0xEF, 0xE2, 0xA7, 0xE1, 0xEB, 0xE6, 0xE0, 0xFA]

    result = []

    for byte in byte404040:
        result.append(chr(byte ^ 0x87))

    print(''.join(result)) # print出來的就是FLAG
    ```
## 4. pyyy
- 下載下來是一個pyc檔
`Note: pyc檔是python用來持久保存pythonCodeObject的方式,當使用python執行一個.py檔時, 會先檢查有沒有.pyc檔存在,如果有就直接使用,如果沒有.pyc或是發現程式碼有異動(接著要再檢查時間),就會進行編譯的動作,執行完成後再把編譯好的pythonCodeObject寫進.pyc`

- 使用uncompyle6來反編譯
`Usage uncompyle6 -o [output.py] [input.pyc]`
![](https://i.imgur.com/LZF5GAy.png)

- pyyy.py
```python=
# uncompyle6 version 3.6.7
# Python bytecode 2.7 (62211)
# Decompiled from: Python 3.6.9 (default, Nov  7 2019, 10:44:02)
# [GCC 8.3.0]
# Embedded file name: pyyy.py
# Compiled at: 2016-06-12 01:14:31
__import__('sys').setrecursionlimit(1048576)

data = 'Tt1PJbKTTP+nCqHvVwojv9K8AmPWx1q1UCC7yAxMRIpddAlH+oIHgTET7KHS1SIZshfo2DOu8dUt6wORBvNVBpUSsuHa0S78KG+SCQtB2lr4c1RPbMf0nR9SeSm1ptEY37y310SJMY28u6m4Y44qniGTi39ToHRTyxwsbHVuEjf480eeYAfSVvpWvS8Oy2bjvy0QMVEMSkyJ9p1QlGgyg3mUnNCpSb96VgCaUe4aFu4YbOnOV3HUgYcgXs7IcCELyUeUci7mN8HSvNc93sST6mKl5SDryngxuURkmqLB3azioL6MLWZTg69j6dflQIhr8RvOLNwRURYRKa1g7CKkmhN4RytXn4nyK2UM/SoR+ntja1scBJTUo0I31x1wBJpT4HjDN47FLQWIkRW+2wnB3eEwO5+uSiQpzA8VaH7VGRrlU/BFW4GqbaepzKPLdXQFBkNyBKzqzR/zA2GIrYbLIVScWJ19DqJCOyVLGeVIVXyzN1y327orYL2Ee3lRITnE3FouicRStaznIcw8xmxvukwVMRZIJ/vTu8Zc1WQIYEIFXMHozGuvzZgROZTyFihWNRCBBtoP9DJJALJb0pA1IKIb2zLh+pwGF40Y6y93D6weKejGPO+A0DBXH9vuLcCcCIvr/XPQhO3jLKCBN+h9unuJKW3dyWxyaVPdR2V+BTw10VXolo7yaTH1GbR4TiVSB308mBOMwfchwihEe7RdMXvmXgaGarKkJe0NLUCd8jwhYII+WymjxO/xOz/ppOvNfAyIQksW0sggRPQTlgXSZ7MIVA1h66sGNljJ833MoFzWof3azLabaz1OrAJFqYXBg/myDsy1tV6rULSQ82hVR/TNnSmBGvyEDJTrLSwHyj78NOrW4mUnlLGBnAgWfw6pW2lRK2jkNX9NM6DfLsRK8lwl85UP8CZSuNdcLmLwHTVMZGm/cNkZCtWRBlZqEggxGdIO44D+f4y6ysnAk5/QzEwjIuecxEOb0jyV6dFui8g0c3Oxlhzcli0X8ToJFyeQRv1N9nokYZ07tFlG6m18kCToKz1qiH1U7kljXa6SvdORur5dWYLQ//gwhwppe7JlNda/cEoh92h96wRZDv1dSK/f1vz+mUeUyUlFY0iMjfw5eBXWZppNZi3ZtJcq5kllM2ACVFcxQWI3azM3ArOcqjosoiPjNoDYgKh7w4k2Cd0kLYEHscz/njtJ1KEcwLtqs4nJ+gB2r4V9g03YgvY5E8JJtfJMKdaTedjtvEuif8FNlCK9DMnL1iLpWptJbdfO83Y7Y46XCqjZFBI5o9Qtb78nLhMEM5/YTaNOM/wE/oJl5HI/i1X6kW3PKCsVubRkOkc2xawl6NYdLETjLvmrGhhI'

a = 138429774382724799266162638867586769792748493609302140496533867008095173455879947894779596310639574974753192434052788523153034589364467968354251594963074151184337695885797721664543377136576728391441971163150867881230659356864392306243566560400813331657921013491282868612767612765572674016169587707802180184907
b = 166973306488837616386657525560867472072892600582336170876582087259745204609621953127155704341986656998388476384268944991674622137321564169015892277394676111821625785660520124854949115848029992901570017003426516060587542151508457828993393269285811192061921777841414081024007246548176106270807755753959299347499
c = 139406975904616010993781070968929386959137770161716276206009304788138064464003872600873092175794194742278065731836036319691820923110824297438873852431436552084682500678960815829913952504299121961851611486307770895268480972697776808108762998982519628673363727353417882436601914441385329576073198101416778820619
d = 120247815040203971878156401336064195859617475109255488973983177090503841094270099798091750950310387020985631462241773194856928204176366565203099326711551950860726971729471331094591029476222036323301387584932169743858328653144427714133805588252752063520123349229781762269259290641902996030408389845608487018053
e = 104267926052681232399022097693567945566792104266393042997592419084595590842792587289837162127972340402399483206179123720857893336658554734721858861632513815134558092263747423069663471743032485002524258053046479965386191422139115548526476836214275044776929064607168983831792995196973781849976905066967868513707
F = (a, b, c, d, e)
m = 8804961678093749244362737710317041066205860704668932527558424153061050650933657852195829452594083176433024286784373401822915616916582813941258471733233011
g = 67051725181167609293818569777421162357707866659797065037224862389521658445401

z = []
for i, f in enumerate(F): #i=0~4, f=a~e
    n = pow(f, m, g) # = pow(f, m)%g
    this_is = 'Y-Combinator'
    l = (lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args))))(lambda f: lambda x: 1 if x < 2 else f(x - 1) * x % n)(g % 27777)
    c = raw_input('Channenge #%d:' % i)
    if int(c) != l:
        print 'Wrong~'
        exit()
    z.append(l)

z.sort()
gg = '(flaSg\'7 \\h#GiQwt~66\x0csxCN]4sT{? Zx YCf6S>|~`\x0c$/}\'\r:4DjJFvm]([sP%FMY"@=YS;CQ7T#zx42#$S_j0\\Lu^N31=r\x0b\t\tjVhhb_KM$|6]\nl!:V\rx8P[0m ;ho_\rR(0/~9HgE8!ec*AsGd[e|2&h!}GLGt\'=$\x0cbKFMnbez-q\\`I~];@$y#bj9K0xmI2#8 sl^gBNL@fUL\x0b\\9Ohf]c>Vj/>rnWXgLP#<+4$BG@,\'n a_7C:-}f(WO8Y\x0c2|(nTP!\'\\>^\'}-7+AwBV!w7KUq4Qpg\tf.}Z7_!m+ypy=`3#\\=?9B4=?^}&\'~ Z@OH8\n0=6\x0b\tv\nl!G\'y4dQW5!~g~I*f"rz1{qQH{G9\x0c\'b\x0cp\x0bdu!2/\\@i4eG"If0A{-)N=6GMC<U5/ds\rG&z>P1\nsq=5>dFZUWtjv\tX~^?9?Irwx\\5A!32N\x0bcVkx!f)sVY Men\x0c\'ujN<"LJ\x0c5R4"\\\\XPVA\'m$~tj)Br}C}&kX2<|\np3XtaHB.P\'(E 4$dm!uDyC%u ["x[VYw=1aDJ (8V/a!J?`_r:n7J88!a25AZ]#,ab?{%e\x0b]wN_}*Q:mh>@]u\t&6:Z*Fmr?U`cOHbAf7s@&5~L ,\tQ18 -Hg q2nz%\x0ccUm=dz&h1(ozoZ)mrA=`HKo\n\'rXm}Z-l3]WgN\\NW<{o=)[V({7<N1.-A8S"=;3sderb\tOZ$K\r0o/5\x0bMc76EGCWJ3IQpr7!QhbgzX8uGe3<w-g\'/j\'\tM4|9l?i&tm_\n57X0B2rOpuB@H@%L_\r)&/q=LZa(%}""#if#Kq74xK?`jGFOn"8&^3Q-\r#]E$=!b^In0:$4VKPXP0UK=IK)Y\rstOT40=?DyHor8j7O\\r/~ncJ5];cCT)c?OS0EM5m#V(-%"Tu:!UsE],0Dp  s@HErS]J{%oH54B&(zE.(@5#2k\tJnNlnUEij\\.q/3HBpJNk*X(k5;DlqK\'\'fX\r}EBk_7\x0b:>8~\t+M@WJx.PO({/U}1}#TqjreG\nN{\rX>4EsJr0Pn\\Z\\aL/-U<<{,Q;j\tF=7f\')+wH:p{G=_.s\\t-\x0bI\x0c*y\t1P:Y|/2xE<uo]~$>5k]FW+>fR<QA"(Fj[LL(hzfQo#PJ;:*0kB~3]9uL[o.xue:VQ\t;9-Tu\tq|mzzhV_okP\t,d\rQ`]5Gf\x0c#gXB\x0cAH|)NI|K=KW-&p-<b"3e.rO\x0cuK=\x0c^\r+MuLxCJ`UKaD\x0bBH&n+YVajZ(U7pwWtto3T10VLHwSJ\rK\t}\'F$l1:b2Bd\na=#t0iq}#!{1_)w$}<Dp(borC\'\t?r6;,+k;a(Q3@B?RCWYEDrjZe![x=n_%S]rl{&fLr*mgCD;92/nNsaxKy/;\nr]sPK=`+YP>MmfB\n8O4/"}nE7r*=41f2\t37>K\'s$wpl;qS[`qzu\x0b\t\nuaU|b,C`4& dRN~]7DnuTb2FhNHV!#Z2Hho\x0b[%.{O\t$q0\x0ch_@?w@b8[I^{JL|O8]i8{p)A.w)14qK3JoyF%licZ~ga\rW[L:W\rtIvfWJjZUOvB\rS.Beav3!-@bw|PexJ Pcw1\ry6!63B}]J])6fak/3r]W\tMeXt[uc(1_U lys{a1X\r%)[wwP3rhgNW{*d~_E%Q2htCt5ha@l0^0=\x0bwT\ni4/V;_\nM1rb?w~Q)Dli4u\n`}1+D8"\t`@V~$9l$Uy**VnI (@Ga0<RxfmoNgJTtE-aLH\rE5fMy7rk$)V\rL2Fv/AivOa"\nuX|70Xrw^D]%i%JyT\x0cc%cwZ/Wbp=IiY;/@nFEe>3=tM;K*`fReGoc5V/Ri?nXZ-RW)\'\t<\x0cV>@X@-Ei4%sO%},B_pjc`s"@oKCmdgDhjUZT@?mb\'?Q:F\x0bLJkPgjaFAc=rbrjAz$Zz\x0cq0GU!")xFOEF(x!3M\t:l83|}}HgGJJ#eT/I\x0b[|lK_n+;Wi/N^B4LzL.a(gVWq,zO6\'S|tb>RX` ca*CO<w\x0ci =wc1,M~\x0bc`FYEs\r){+Ll8[I9-88m\t\\iK/\\hno-C[vX*3Hx:%:K\rt\x0cW!tj\'SOhqxP|k7cw Hm?I@?P\'HmapG7$0#T(Auz]sjmd#\rFP/}53@-Kvmi(d%dZKLZ2LK\'e_E\x0bQmR 5/(irq4-EUyp<hB?[\tnU:p*xuzASM'
print ('').join(gg[(lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args))))(lambda f: lambda n: 1 if n < 3 else f(n - 1) + f(n - 2))(i + 2)] for i in range(16)) % ('').join(data[pow((__import__('fractions').gcd(z[(i % 5)], z[((i + 1) % 5)]) * 2 + 1) * g, F[(i % 5)] * (i * 2 + 1), len(data))] for i in range(32))
```

- 可以看出問題應該出在第26~28行,因為比較錯誤執行了exit(),註解掉那邊的code試試看
```python=25
    c = raw_input('Channenge #%d:' %i)
#    if int(c) != l:
#        print 'Wrong~'
#        exit()
    z.append(l)
```
- 因為是append(l),所以輸入的對不對根本不影響結果
![](https://i.imgur.com/I6aKQrV.png)

## 5. accumulator
- 先執行看看
![](https://i.imgur.com/hhC2F0o.png)
- file看一下發現是stripped的
![](https://i.imgur.com/ZUhJUfb.png)
- 用gdb找stripped file的main function的方式
    :::success
    1. info files
    ![](https://i.imgur.com/ZNP8T7L.png)
    2. 重點是entry point在0x4007d2 => 下斷點在這邊就可以直接r了
    3. 接下來ni逐步找,直到找到__libc_start_main, 這個function的第一個參數會把main function作為function ptr傳入,下面是他的prototype
        ```c=
        int __libc_start_main(int (*main) (int, char **, char **), int argc, char ** ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (*stack_end));
        ```
        ![](https://i.imgur.com/nLtkv4O.png)

    4. 所以可以知道0x400710應該就是main function的位置,用x/50i 0x400710就可以列出50條assembly, 開始逆向囉<3
    :::
- main function大概逆一下
1. __printf_chk: 
    ```
    int __printf_chk(int flag, const char * format)
    ```
    :::info
    跟printf()類似, 但format string攻擊時必須同時使用%(第幾個參數)$s,且禁用%n, 
    flag>0時,代表__USE_FORTIFY_LEVEL>1, 數字越大安全性越高
    :::
```asm=
gdb-peda$ x/50i 0x400710
   0x400710:    push   rbx
   0x400711:    mov    esi,0x4009e0
   0x400716:    mov    edi,0x1
   0x40071b:    xor    ebx,ebx
   0x40071d:    sub    rsp,0x450
   0x400724:    mov    rax,QWORD PTR fs:0x28
   0x40072d:    mov    QWORD PTR [rsp+0x448],rax
   0x400735:    xor    eax,eax
   0x400737:    call   0x4006c0 <__printf_chk@plt>
                  # x/s 0x4009e0 => 知道這邊放的是what's your flag?:字串
                  # __printf_chk(1, 0x4009e0)
```
2. getc(stdin): 每次接收一個byte,輸入幾個byte執行幾次
```asm=13
    0x40073c:    jmp    0x400755
    0x40073e:    xchg   ax,ax
    0x400740:    cmp    al,0xff
    0x400742:    je     0x400765
    0x400744:    add    rbx,0x1
    0x400748:    cmp    rbx,0x400
    0x40074f:    mov    BYTE PTR [rsp+rbx*1+0x3f],al
    0x400753:    je     0x400765
    0x400755:    mov    rdi,QWORD PTR [rip+0x200c44]        # 0x6013a0 <stdin>
    0x40075c:    call   0x4006e0 <_IO_getc@plt>
    0x400761:    cmp    al,0xa   #讀到空字串就不跳
    0x400763:    jne    0x400740         
```
3. SHA512(&input, input_size, &hash) -> 把hash結果放進&hash中
=> hash結果放在stack上作為回傳值(rax指向&hash=rsp)
![](https://i.imgur.com/DG6dgUQ.png)
4. 謎樣function 0x4008c0
```asm=31
    0x0040077a      be40000000     mov esi, 0x40           
    0x0040077f      4889e7         mov rdi, rsp
    0x00400782      e839010000     call 0x4008c0  # 0x4008c0(&hash,0x40)
    0x00400787      488d7c2440     lea rdi, qword [rsp-0x40]
    0x0040078c      4889de         mov rsi, rbx
    0x0040078f      e82c010000     call 0x4008c0
    0x00400794      bff9094000     mov edi, str.Good_flag_for_you. ; 0x4009f9 ; "Good flag for you."
    0x00400799      e802ffffff     call sym.imp.puts           ; int puts(const char *s) 
   ```
:::info
1. 如果getc時隨意輸入會發現執行第一次的0x4008c0就會直接跳'bad flag :('然後結束process
因此這個function應該就是檢查hash結果的地方 
2. 想要順利得到Good_flag_for_you字串只能讓檢查都通過(因為0x4008c0的assembly中並沒有跳到0x400794的指令)
    => 也就是說,0x4008c0必須可以執行到ret
:::

- 0x4008c0
    :::success
    目標: 執行到第28行的ret,不可以執行到call exit => **不可以跳到0x400932**
    :::
    這邊用r2,但其實用gdb實際跑更簡單
    :::info
    note: rdi=&hash, rsi=0x40
    1. 第19行~29行是個迴圈
    2. 因此在這之前應該是在做迴圈的初始
        1. 第7~第9行,edx放hash[0],0x6013c0初始值0
        2. 第10&14行,檢查hash[0]跟0x601080的內容有沒有相同(=0xC3),,沒有就bad flag
        3. 第12行,把hash[0]放進0x6013c0
        4. 第11&13行, 0x6013b0=ecx作為counter
        5. 第15行,rax指向hash下一個byte
        6. 第16行,rsi=rdi+0x40指向hash尾+1(因為SHA512產生0x40=64byte)
        7. 第28行,比較rax是否到了hash尾+1,如果沒有就開始迴圈
    3. 迴圈部分
        1. r8 = rax
        2. rax指向下一個hash byte
        3. rdx會累加所有hash byte並放進0x6013c0
        4. rcx跟0x6013b0為counter
        5. rdx跟0x601080+4*rcx內容要相同才會繼續迴圈
    4. 看一下0x601080那邊的內容...超級多QQ
    ![](https://i.imgur.com/qNm8X6G.png)        
    :::
    
```c=
    [0x004008c0]> pd
               ; CALL XREF from 0x00400782 (main)
               ; CALL XREF from 0x0040078f (main)
            0x004008c0      4883ec08       sub rsp, 8
            0x004008c4      4885f6         test rsi, rsi
        ,=< 0x004008c7      7464           je 0x40092d
        |   0x004008c9      8b05e10a2000   mov eax, dword [0x006013b0] ; [0x6013b0:4]=0
        |   0x004008cf      0fb617         movzx edx, byte [rdi]
        |   0x004008d2      0315e80a2000   add edx, dword [0x006013c0]
        |   0x004008d8      3b1485801060.  cmp edx, dword [rax*4 + 0x601080] ; [0x601080:4]=195
        |   0x004008df      8d4801         lea ecx, dword [rax + 1]    ; 1
        |   0x004008e2      8915d80a2000   mov dword [0x006013c0], edx ; [0x6013c0:4]=0
        |   0x004008e8      890dc20a2000   mov dword [0x006013b0], ecx ; [0x6013b0:4]=0
       ,==< 0x004008ee      7542           jne 0x400932
       ||   0x004008f0      488d4701       lea rax, qword [rdi + 1]    ; 1
       ||   0x004008f4      4801fe         add rsi, rdi                ; '''
      ,===< 0x004008f7      eb2f           jmp 0x400928
      |||   0x004008f9      0f1f80000000.  nop dword [rax]
     .----> 0x00400900      440fb600       movzx r8d, byte [rax]
     :|||   0x00400904      4883c001       add rax, 1
     :|||   0x00400908      4401c2         add edx, r8d
     :|||   0x0040090b      3b148d801060.  cmp edx, dword [rcx*4 + 0x601080] ; [0x601080:4]=195
     :|||   0x00400912      448d4101       lea r8d, dword [rcx + 1]    ; 1
     :|||   0x00400916      8915a40a2000   mov dword [0x006013c0], edx ; [0x6013c0:4]=0
     :|||   0x0040091c      4489058d0a20.  mov dword [0x006013b0], r8d ; [0x6013b0:4]=0
    ,=====< 0x00400923      750d           jne 0x400932
    |:|||   0x00400925      4489c1         mov ecx, r8d
    |:`---> 0x00400928      4839f0         cmp rax, rsi
    |`====< 0x0040092b      75d3           jne 0x400900
    |  |`-> 0x0040092d      4883c408       add rsp, 8
    |  |    0x00400931      c3             ret
    `--`--> 0x00400932      bfd4094000     mov edi, str.Bad_flag_:     ; 0x4009d4 ; "Bad flag :("
            0x00400937      e864fdffff     call sym.imp.puts           ; int puts(const char *s)
            0x0040093c      bf01000000     mov edi, 1
            0x00400941      e86afdffff     call sym.imp.exit           ; void exit(int status)
```

- 寫個python script來炸flag
```python=
text = [0x00c3, 0x00ff, 0x01ed, 0x0248, 0x031f, 0x03a1, 0x03b2, 0x043e, 0x049c, 0x04a0, 0x058d, 0x063b, 0x070d, 0x0736, 0x0821, 0x0910, 0x097e, 0x0a2d, 0x0aa7, 0x0b9c, 0x0c8d, 0x0d4b, 0x0d5a, 0x0e41, 0x0e80, 0x0f6e, 0x0f95, 0x1061, 0x1084, 0x112a, 0x11ab, 0x1210, 0x1262, 0x1347, 0x1387, 0x13d0, 0x13f2, 0x14ab, 0x1586, 0x15a0, 0x160c, 0x1677, 0x1769, 0x17e6, 0x17ee, 0x1836, 0x1843, 0x190a, 0x1945, 0x19d1, 0x19f7, 0x1a60, 0x1b42, 0x1b62, 0x1b8d, 0x1bc2, 0x1c6a, 0x1d2c, 0x1d8b, 0x1df9, 0x1e1a, 0x1f14, 0x1fd2, 0x1ffb, 0x2041, 0x208d, 0x20ce, 0x2115, 0x2190, 0x21c0, 0x21f5, 0x2226, 0x2259, 0x228c, 0x22c5, 0x22f9, 0x232f, 0x2366, 0x2399, 0x23c9, 0x23ff, 0x2465, 0x249e, 0x24d5, 0x250b, 0x2544, 0x2577, 0x25ac, 0x25dc, 0x260d, 0x2640, 0x2676, 0x26d8, 0x270c, 0x273d, 0x27a0, 0x27d3, 0x2806, 0x2836, 0x286e, 0x28a2, 0x28d2, 0x2937, 0x299c, 0x29fe, 0x2a61, 0x2ac2, 0x2b25, 0x2b58, 0x2b8b, 0x2bc2, 0x2c28, 0x2c59, 0x2cbb, 0x2cf3, 0x2d55, 0x2d85, 0x2de9, 0x2e4c, 0x2e7c, 0x2eaf, 0x2f14, 0x2f49, 0x2f81, 0x2fe3, 0x3048, 0x3079, 0x30ad, 0x3113, 0x3178, 0x31ae, 0x31e7, 0x3217, 0x3279, 0x32aa, 0x32dc, 0x330f, 0x3375, 0x33ab, 0x33dc, 0x343e, 0x346e, 0x34d1, 0x3501, 0x3563, 0x3596, 0x35cb, 0x3631, 0x3694, 0x36cd, 0x3700, 0x3763, 0x37c6, 0x3829, 0x3860, 0x3892, 0x38c3, 0x38f3, 0x3923, 0x3957, 0x398c, 0x39c5, 0x39f8, 0x3a2e, 0x3a67, 0x3acc, 0x3b32, 0x3b6a, 0x3b9f, 0x3bd2, 0x3c03, 0x3c64, 0x3c95, 0x3cfa, 0x3d32, 0x3d93, 0x3dca, 0x3e2c, 0x3e60, 0x3e92, 0x3ecb, 0x3f04, 0x3f69, 0x3fa0, 0x4002, 0x403b, 0x409f, 0x40d8, 0x410f, 0x413f, 0x41a1, 0x41da, 0x423b, 0x426d, 0x42a0, 0x4301, 0x4362, 0x43df]

flag = ""
for i in range(1,len(text)):
	flag += chr(text[i] - text[i-1])

print(flag)
```

## 6. gccc
- 是一支用C#寫的.net程式
=> .net反組譯工具 : ILspy
- 反組譯結果
```clike=
// GrayCCC
using System;

public class GrayCCC
{
	public static void Main()
	{
		Console.Write("Input the key: ");
		if (!uint.TryParse(Console.ReadLine().Trim(), out uint result))  
                //trim():去除頭尾空白字元
                //TryParse(string str, out uint result) => 把數字字串轉成對應的無號數(uint),結果放在result中
		{
			Console.WriteLine("Invalid key");
			return;
		}
		string text = "";
		string text2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ{} ";
		int num = 0;
		byte[] array = new byte[32]
		{
			164, 25, 4, 130, 126, 158, 91, 199, 173, 252, 239, 143,	150, 251, 126, 39, 104, 104, 146, 208, 249, 9, 219,	208, 101, 182, 62, 92, 6, 27, 5, 46
		};
		byte b = 0;
		while (result != 0)
		{
			char c = (char)(array[num] ^ (byte)result ^ b); 
			if (!text2.Contains(new string(c, 1)))
			{
				Console.WriteLine("Invalid key");
				return;
			}
			text += c;
			b = (byte)(b ^ array[num++]);
			result >>= 1;
		}
		if (text.Substring(0, 5) != "FLAG{" || text.Substring(31, 1) != "}")
		{
			Console.WriteLine("Invalid key");
		}
		else
		{
			Console.WriteLine("Your flag is: " + text);
		}
	}
}
```
- Summary:
    :::info
    1. 目標是解出result,第24行限制result轉換出來的無號數一定要剛好32bit(ie 範圍2^32~ 2^31+1)
    2. 每次result右移1bit, 總共驗證32輪(因為有32bit)
        c = char(array[i] ^ result ^ b)
        c的範圍只能在ABCDEFGHIJKLMNOPQRSTUVWXYZ{}中
        b第一輪為0,每一輪結束後b ^= array[i]
    :::
    
- 用z3 solver解
```python=
from z3 import *

array = [164, 25, 4, 130, 126, 158, 91, 199, 173, 252, 239, 143, 150, 251, 126, 39, 104, 104, 146, 208, 249, 9, 219, 208, 101, 182, 62, 92, 6, 27, 5, 46]

result = BitVec('result', 64)  # BitVec(name, size)

solver = Solver()

solver.add(result >= 2**31)
solver.add(result < 2**32)

b = 0

for i in range(32):
    if i < 5:
        solver.add((array[i] ^ b ^ result) & 0x7f == ord('FLAG{'[i]))
        # & 0x7f的原因是因為要轉成char, char範圍是0~127(0x7f)
    elif i == 31:
        solver.add((array[i] ^ b ^ result) & 0x7f == ord('}'))
    else:
    # And/Or中間的條件用','分隔
        solver.add(
            Or(
                And(
                    ((array[i] ^ b ^ result) & 0x7f >= ord('A')),
                    ((array[i] ^ b ^ result) & 0x7f <= ord('Z'))
                ),
                   ((array[i] ^ b ^ result) & 0x7f == ord(' '))
            )
        )

    b ^= array[i]
    result >>= 1

if solver.check() == sat:
    print(solver.model())
```
- 用cmd執行一次gccc.exe並送出解出來的數字
![](https://i.imgur.com/dsAJUal.png)


## 7. ccc
- ida main
    :::info
    1. read讀取輸入,回傳值(eax)為input size,再push到stack上作為verify的第二個參數
    2. call verify之後test eax, eax看是否=0
        - 第一個參數為input,第二個參數為input size
        - =0就到QQ,如果要達成Good就要讓eax=1
    :::
    ![](https://i.imgur.com/Y2WoJYQ.png)

- verify
    :::info
    1. 一開始就先cmp size是否為0x2a
    2. 由右邊第二格cmp eax,size之後,如果小於等於就跳,直到等於時跳出迴圈&eax=1, 
        ->代表這邊有個迴圈,eax中放i,最底最右邊顯示每次i+=3,因此應該迴圈會做0x2a//3==14次
    4. 右邊第三格,每個循環call一次crc32(0, &input, i),結果放在ecx中
    5. cmp ecx, eax -> eax放hashes[count:從0開始計算迴圈次數]跟crc32做出來的結果比較,ZF=1(相等)才做下一輪,否則ret 0
    :::
    ![](https://i.imgur.com/dbL226V.png)
    
- crc32
    :::info
    1. 中間的那格,test eax,eax看eax是否為0,如果=0就ret
        - eax放verify傳過來的i(是3,6,9,...,0x2a)
        - i每輪都-1 (所以第一次crc做3,第二次crc做6
    2. 底下右邊那格, result這個變數經過運算之後再做not運算, 即crc32的ret value
    3. result被verify傳入時為0,一開始先將0做not運算=0xffffffff, 才開始進入迴圈
    4. 左下那格: result = (result >> 8) ^ crc32_tab[下面講]
        - 下面講 : 將input[從0~i-1]跟result做xor,再取最後兩個byte(al)
    :::
    ![](https://i.imgur.com/fPgq1Ls.png)
    
- 寫個python script暴力破flag
    ```python=
    import string

    crc32_tab = [0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,37721115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,18432558603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,9970773096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,28988065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,34855111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,311158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,21377656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,41111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,27477007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,8555842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,15591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,19557810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,1677816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,23112317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,35118719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,11181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,7733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,39943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,22662029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,2885281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,12231636301,1047427035,2932959818,3654703836,1088359270,936918000,2847714899,3736837829,1202900863,817233897,3183342108,33401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,33020668471,3272380065,1510334235,755167117]
    hashes = [3594606959,2158225808,3381484699,218476463,326279469,1566511483,1073871869,2815612267,2097478526,776112478,1640595123,2225816515,2680236509,4099485517,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295]

    def crc32(input,size):
        i = 0xffffffff
        for x in range(size):
            i = (i >> 8) ^ (crc32_tab[(i ^ int(input[x].encode().hex(),16)) & 0xff])
        return (0xffffffff - i) #not operation: -1(111) - 5(0101) = 6 (1010)

    flag = ''
    for count in range(14):
        for i in string.printable:
            for j in string.printable:
                for k in string.printable:
                    test_flag = flag + i + j + k
                    if (crc32(test_flag, len(test_flag)) == hashes[count]):
                            flag = test_flag
                            count += 1
                            print(f'{count} : {flag}')
    print(flag)
    ```
    ![](https://i.imgur.com/hBkULcP.png)
    
    :::warning
    **Note: ida trick**
    1. 在data上按d可以切換db, dw, dd,如果有一堆資料要轉成dd,可以先將第一個轉成需要的type,再按Alt+L以及滑鼠滾動選取需要的部分,就可以一次按d轉成跟第一個同樣type
    2. shift+e可以dump需要的內容
    3. shift+f2可以寫idc腳本
        ```c=
        auto i, fp;
        fp = fopen("c:\\dump_mem.bin", "wb"); //需要的部分dump成binary
        for (i=start_addr; i<=end_addr; i++)
            fgetc(Byte(i),fp); //或WordDword(),Word()
        ```
    :::

## 8. bitx
- ida看main
    :::info
    目標是test eax,eax檢查eax!=0
    --> verify(input)= 1
    :::
    ![](https://i.imgur.com/M0kpcKg.png)
- verify()
    :::info
    verify() == 1有兩條路
    1. input_flag走到字串尾(0x0)
    2. 0x804040+i為0x0 (data最後一個byte是0)
        ![](https://i.imgur.com/BCGnIGZ.png)
    這邊有個loop,每次i+1,並分別對flag跟data做運算之後比較結果
    :::
    ![](https://i.imgur.com/RkQtEqv.png)
    - 還原程式碼大概是這樣
    ```python=
    def verify(flag):
    for i in range(len(flag)):
        if ((int(flag[i].encode().hex(),16)+9) != (((data[i] & 0xaa) >> 1) | (2*(data[i] & 0x55)))):
            return 0
    return 1
    ```
- 一樣寫個python script來還原flag吧
```python=
data = [0x8F, 0xAA, 0x85, 0xA0, 0x48, 0xAC, 0x40, 0x95, 0xB6, 0x16, 0xBE, 0x40, 0xB4, 0x16, 0x97, 0xB1, 0xBE, 0xBC, 0x16, 0xB1, 0xBC, 0x16, 0x9D, 0x95, 0xBC, 0x41, 0x16, 0x36, 0x42, 0x95, 0x95, 0x16, 0x40, 0xB1, 0xBE, 0xB2, 0x16, 0x36, 0x42, 0x3D, 0x3D, 0x49, 0x00]

def solution():
    flag = ''
    for i in range(len(data)-1):
        rhs = ((data[i] & 0xaa) >> 1) | (2 * (data[i] & 0x55))
        flag_i = rhs - 9
        flag += chr(flag_i)
    print(flag)

solution()

```


## 9. 2018-rev
- file之後發現是一個stripped的檔案
    ![](https://i.imgur.com/lvtt2bz.png)
- 先執行一次
    ![](https://i.imgur.com/RVqA9U6.png)
- 丟進ida看
    - start
        :::info
        1. 在剛開始執行時,會把參數倒序+argc push到stack上
            ex. gdb> r aaa 
            會依序push aaa, binary_path, 0x2(2個arg) (0x4009d0是entry pt)
             ![](https://i.imgur.com/GMxjXvf.png)
           因此第三行的pop rsi就相當於把stack頂的argc pop給rsi
           第四行的mov rdx, rsp相當於把binary_path傳給rdx
           第五行對rsp & 0xFF...F0是為了要讓stack是0x10對齊
        2. 最底下的call猜測可能是__libc_start_main,這個function會把main function ptr當作第一個參數,所以0x4005f0應該就是main function的起始位置
        Note: 0x4005f0原本只是個location,可以右鍵找Create function讓他解析成function
        :::
        ![](https://i.imgur.com/3CM75Ur.png)
        
    - 接下來就可以看main惹
        - 第一階段的重點是這三個連續cmp
        ![](https://i.imgur.com/KWavpnP.png)
            - 這邊可以寫一個gdb script來bypass
                :::info
                1. 直接在gdb裡面 > define myscript 
                    ![](https://i.imgur.com/3ct6fZq.png)
                2. 創建一個 **.gdb**檔
                    ```c=
                    //2018_rev.gdb

                    b *0x4005f0
                    r

                    set $rdi = 0x7e2
                    set {long}0x7fffffffe6b3=0x1
                    set {long}0x7fffffffe682=0x1

                    c
                    ```
                    ![](https://i.imgur.com/bGQ7b9f.png)
                :::
        - 但接著執行下去就會遇到第二個關卡
            ![](https://i.imgur.com/hSlF7yj.png)
            - 這邊也有三個連續c,而且跟rbx都有關,一樣用gdb script bypass,比較通過之後就可以calc_flag
                ![](https://i.imgur.com/zf1OzLW.png)
                
                :::info
                看gdb可以知道rbx = 0x6ce2a0,繼續用gdb script
                ```c=
                b *0x4005f0
                r

                set $rdi = 0x7e2
                set {long}0x7fffffffe6b3=0x1
                set {long}0x7fffffffe682=0x1

                c
                b *0x40065d

                set {long}0x6ce2a0=0x0
                set {long}0x6ce2a8=0x100000000
                set {long}0x6ce2b0=0x7600000000

                c
                ```
                :::
            - 但出來的flag長得很奇怪QQ
                ![](https://i.imgur.com/sJRRGHo.png)
                - 看了一下calc_flag,flag的每個byte應該都是經由0x6cde20+i跟0x6cb0a0+i做xor運算的結果出來的
                    ![](https://i.imgur.com/T1AMJJ1.png)
                - 而0x6cde20可以由上一張圖得知被放進了一堆0x9e,又對其中幾個byte做了一些改變
                    ![](https://i.imgur.com/5fqxFYx.png)
                    
                    :::info
                    - 第一次改變只是改成0x7e2
                    - 第二次的改變跟rdx有關係,而此時rdx由r12來的,而r12是arg的位址
                        ![](https://i.imgur.com/EgRfsf1.png)
                    - 第三次改變也跟rdx有關係,但此時rdx是由rbp來的,而rbp是環境變數的位址
                        ![](https://i.imgur.com/YJKrygg.png)
                    - 然後0x6cde28跟0x6cde30也會被rax改變,rax是就是執行sys_time之後得到的系統時間轉成的特定格式...下面的var38經由gdb確認之後就是sys_time執行的結果(或是rsp+38h-38h = rsp也可以知道)
                        ![](https://i.imgur.com/MPNXwsW.png)
                    - 總之還是要想辦法改變系統時間QQ
                    :::
                - 從sys_time執行後的那個function進去看,可以發現是從/etc/localtime取得運行時間的
                    ![](https://i.imgur.com/5mx0d4H.png)
                    - sudo date可以短暫修改/etc/localtime,但很快就會被改回來(因為系統會根據時區抓取時間)
                        ![](https://i.imgur.com/WtKtLHK.png)
                        所以可以寫個bash script不斷執行sudo date修改/etc/localtime,再執行gdb script,這樣就可以順利得到美美的flag
                        ```python=
                        #2018_rev.sh > ./2018_rev.sh即可執行                      
                        #!/usr/bin/env bash

                        while true
                        do
                                sudo date -us "2018-01-01 00:00:00"
                        done
                        ```
                        
## 10. what-the-hell
- main
    :::info
    簡單來說就是會有兩個輸入,丟進calc_key3做運算,算出來的結果丟給decrypt_flag來算出flag
    :::
    
    ![](https://i.imgur.com/69Aq6eP.png)
- 而calc_key3需要先滿足某些條件才會繼續執行
    :::info
    1. input1 * input2 == 0xddc34132
    2. (input2 + 0x10) * (input1 ^ 0x7e) == 0x732092be
    3. (input1 - input2) & 0xfff == 0xcdf
    4. input1是質數
    ![](https://i.imgur.com/USBs9ML.png)
    5. 最後有個小迴圈
    ![](https://i.imgur.com/UDYQHSv.png)
        - what()就是在執行fib計算 -->這就是題目說something slow的原因
        ![](https://i.imgur.com/mxcJGDF.png)
- 上吧z3(?
    ```python=
    from z3 import *
    from gmpy2 import *  #用sympy不知道為啥會報錯QQ

    a2 = BitVec('a2', 32)
    a1 = BitVec('a1', 32)

    s = Solver()
    s.add(a1 * a2 == 0xddc34132)
    s.add((a2 + 0x10) * (a1 ^ 0x7e) == 0x732092be)
    s.add((a1 - a2) & 0xfff == 0xcdf)

    while (s.check() == sat):
        if is_prime((s.model()[a1].as_long())):
            print(s.model())
        s.add(Or(a1!=s.model()[a1], a2!=s.model()[a2])) #避免重複輸出
    ```
- 但是還沒完,兩個答案都算超久還算不出flag,因為問題出在上面的what,這種算費式數列的方法要花很久的時間
    ![](https://i.imgur.com/1bP1ClQ.png)
    - 但其實出題者還偷偷寫了一個fast_what的function,可以比較快的算出費式數列
        ![](https://i.imgur.com/h01EyAs.png)
- 所以只要把call what patch成call fast_what就可以惹
    - 選中要patch的地方,Edit > patch program > assemble就可以改指令,接著再Edit > patch program > Apply patches to input file就可以成功修改了
        但另一組數字一樣算不出來,猜測應該是因為不是費氏數,所以calc_key3的loop就一直執行下去惹
        ![](https://i.imgur.com/F2Em0NO.png)

    


    


                    




