2021 SCIST Security Reverse Write-up


因為是一年前隨手記錄的東西所以稍微有點雜 ><

CTFd


Practice

picoCTF 2019 asm2

What will asm2(0x6,0x24) return?

sol

a = 0x24 #ebp-0x4
b = 0x6 # ebp-0x8
while(b <= 0x3c75):
        a +=1
        b += 0xf9
print(a)

Ans 99

Level 0

hexedit

可以直接 strings 找到

flag easyctf{eb04fadf}

hexable

一樣是 strings

flag easyctf{abcdef__123456}

CSIE_strace

先去strace看看,會發現它有噴 flag 出來
但是 flag 太長了 有 36 個字,沒辦法全部顯示出來

我們可以用 man 去看看 strace 有甚麼 OPTIONS

man strace

找到了!strace預設的顯示字元長度是32
所以我們把它改成36就可以了!

strace -s 36 ./strace

Flag FLAG{____yaaaa_flag_in_the_stack___}

EasyCTF_adder

IDA Pro 開起來,可以看到 std::istream::operator>>(int &) ,代表它會 cin 3 個數字

把它們換成好辨識的名字後看 pseudocode(F5),可以看到三個相加為 1337 就會給 Flag

Flag EasyCTF_adder

picoCTF2017_Coffee

下載之後看到是.class
可以丟到網路上去反編譯
Decompilers online

translate to python

from base64 import b64decode as b64d
s = "eux_Z]\\ayiqlog`s^hvnmwr[cpftbkjd"
s2 = "Zf91XhR7fa=ZVH2H=QlbvdHJx5omN2xc"
s = s.encode('latin-1')
s2 = s2.encode('latin-1')
a = []
b = ""
for i in range(len(s2)):
    #print(s2[s[i]-90])
    a.append(str(s2[s[i] - 90]))
    b += chr(s2[s[i] - 90])
print(a)
print(b)
print(b64d(b))

flag flag_{pretty_cool_huh}

EasyCTF_LuckyGuess

下載後一樣可以看到 guess 是一個 exe 檔

所以去執行看看,會發現是猜數字的程式碼

我們可以去看一下它的 asm
objdump -d ./guess | less

發現它會去cmp(比較),如果jne(不相等)就會跳到其他地方

那我們可以把在cmp完之後讓他nop
這樣就不會跳轉了~
可以使用 hexedit 來改 machine code

hexedit install:
sudo apt install hexedit

hotkey
ctrl+w : search
ctrl+x : save+quit

可以使用 pwntools 裡面的asm去把 asm 轉換成 machine code

hexedit ./guess
找到

此時再重新去 objdump 看一次的話就會發現已經變成 nop 了!

所以執行並隨便輸入一個數字就可以了

flag flag{aaA_tOucH_0f_luccK_47ca4e}

EasyCTF_liar

先丟進去 IDA Pro 看 pseudo code (偽代碼)

得到 f 之後再丟進去 python

a = [101 , 102 , 125 , 108 , 127 , 87 , 76 , 74 , 75 , 75 , 47 , 33 , 56 , 4 , 21 , 8 , 3 , 25 , 89 , 241 , 211 , 231 , 245 , 206 , 247 , 205 , 215 , 217 , 232 , 148 , 160 , 176 , 135 , 143 , 154 , 202 , 129]

題目有給前七個g[i],所以我們可以透過這七個來推 m

g = [101 , 97 , 115 , 121 , 99 , 116 , 102]
b = []
for i in range(1,7):
        b.append(g[i] ^ a[i])

print(b)
m = b[2]//3
print(m)

得到 m 之後再把剩下的 g 算完就可以了!

flag = ""
for i in range(7,37):
        g.append((m*i) ^ a[i])
for i in range(37):
        flag += chr(g[i])
print(g)
print(flag)

script

a = [101 , 102 , 125 , 108 , 127 , 87 , 76 , 74 , 75 , 75 , 47 , 33 , 56 , 4 , 21 , 8 , 3 , 25 , 89 , 241 , 211 , 231 , 245 , 206 , 247 , 205 , 215 , 217 , 232 , 148 , 160 , 176 , 135 , 143 , 154 , 202 , 129]

g = [101 , 97 , 115 , 121 , 99 , 116 , 102]
b = []
c = []
for i in range(1,7):
        b.append(g[i] ^ a[i])

print(b)
m = b[2]//3
print(m)

flag = ""
for i in range(7,37):
        g.append((m*i) ^ a[i])
for i in range(37):
        flag += chr(g[i])
print(g)
print(flag)

flag
easyctf{still_wasn't_too_bad,_right?}

Level 1

Reverse

先丟進去 IDA Pro 看看
發現可以直接找到 flag 驚喜吧w

flagBreakALLCTF{4U49uY7OJCrJL0vtbXjd}

林思辰_find

strings
運用grep來擷取關鍵字

林思辰_run-asm

先去看看檔案裏面有甚麼

global _start

section .text
_start:
  mov rax, 1
  mov rdi, 1
  push 0x7d214e75
  push 0x525f646e
  push 0x345f6d53
  push 0x615f6531
  push 0x69706d30
  push 0x437b4654
  push 0x43747372
  push 0x6946794d
  mov rsi, rsp
  mov rdx, 0x40
  syscall

  mov rax, 60
  mov rdi, 0

push進去的東西拿出來看看
因為push是 FILO(先進後出),所以順序是由底端到頂端

flagMyFirstCTF{C0mpi1e_aSm_4nd_RuN!}

Level 2

林思辰_base64


把我們找到的那一串奇怪的字串拿去 base64 decode

發現是push

flagMyFirstCTF{Y0U_FlnD_m4G1c_StRinG!!!}

林思辰_encrypt

丟進去 IDA Pro 看看
我們要做的事情是”找出加密的方法並解密一個特別的字串”

稍微美化一下 item 名稱之後看一下這個程式碼在做甚麼

可以看到輸入的 39 個字會依照 ASCII 數值被拆成 3 種

  1. 1-31 || 127 :+0 -> 1-31 || 127
  2. 32-81 :+45 -> 77-126
  3. 82-126 :-50 -> 33-76

我們得到加密的方法了!
只要從字串的 ASCII 碼逆推回原本的數值就可以了
現在要來找特別的字串

shift+F12 可以看到有一個奇怪的字串

於是我們可以寫一個程式去跑這行字串

s = 'zGs7@ABp"sIp/3bn@-:A-G]CllNNK'

flag = ''

for i in s:
    a = ord(i)
    if(a<=31 or a==127):
        flag += chr(a)
    elif(a<=76):
        flag += chr(a+50)
    else:
        flag += chr(a-45)

print(flag)            

flag MyFirstCTF{Cae5Ar_ls_y0u??!!}

林思辰_mutate

丟進去 IDA Pro 看看

我們去看一下 a 裡面是甚麼(點兩下)

shift+E 導出數據,選擇 十進位 txt 檔案

透過xor的可逆性

script

a = [
  109,   0,   0,   0,  88,   0,   0,   0, 100,   0,
    0,   0,  74,   0,   0,   0,  86,   0,   0,   0,
   86,   0,   0,   0,  82,   0,   0,   0, 100,   0,
    0,   0, 124,   0,   0,   0, 111,   0,   0,   0,
   81,   0,   0,   0,  89,   0,   0,   0,  31,   0,
    0,   0, 123,   0,   0,   0,  75,   0,   0,   0,
   93,   0,   0,   0,  99,   0,   0,   0,  84,   0,
    0,   0, 109,   0,   0,   0, 107,   0,   0,   0,
    4,   0,   0,   0,  71,   0,   0,   0, 105,   0,
    0,   0,   6,   0,   0,   0, 107,   0,   0,   0,
  102,   0,   0,   0,  76,   0,   0,   0,   8,   0,
    0,   0, 110,   0,   0,   0, 100,   0,   0,   0,
   97,   0,   0,   0,  90,   0,   0,   0, 116,   0,
    0,   0,  50,   0,   0,   0,  59,   0,   0,   0,
   28,   0,   0,   0,   2,   0,   0,   0,  42,   0,
    0,   0,  20,   0,   0,   0,  24,   0,   0,   0,
   37,   0,   0,   0, 122,   0,   0,   0,  55,   0,
    0,   0,  75,   0,   0,   0,  76,   0,   0,   0,
   77,   0,   0,   0,  78,   0,   0,   0,  79,   0,
    0,   0,  80,   0,   0,   0,  81,   0,   0,   0
]

b = ""
num=0

for i in a:
        if(i):
                b += chr(((num+32) ^ i))
                num+=1

print(b)

陳廷宇_XorZero

一個工具題
運用到一點點 XOR+詞頻分析

可以丟到 XOR Cracker上面去解

把檔案下載下來
strings就可以看到flag了

flag BreakAllCTF{X0r_1s_s0m37h1ng_funny}

林思辰_encode

丟進去 IDA Pro 看看

v = 44099282625849925
a = ""
while(v):
        for j in range(26):
                tmp=v-j
                if(tmp%26==0):
                        a+=(chr(j+65))
                        v=tmp//26
                        break
print(a[::-1])

flag MyFirstCTF{MAKECHRTOINT}

lab

ptrace_me

hoo.c

int ptrace(){
        return 0;
}

gcc -fPIC -shared -o hook.so hook.c

LD_PRELOAD=./hook.so strace ./ptrace_me

darkCON_Too_Much

script

from angr import *
from claripy import *

bin = './rev'

p = Project(bin, auto_load_libs=False)

flag_chars = [BVS(f'flag_{i}',8) for i in range(200)]
flag = Concat(*flag_chars)

st = p.factory.entry_state(stdin=flag)

sm = p.factory.simgr(st)

sm.explore(find=lambda s: b'Congrats' in s.posix.dumps(1),
                avoid=lambda s: b'Please' in s.posix.dumps(1))

for s in sm.found:
        print(s.posix.dumps(0))

flag

darkCON{4r3_y0u_r34lly_th1nk1n9_th4t_y0u_c4n_try_th15_m4nu4lly???_Ok_I_th1nk_y0u_b3tt3r_us3_s0m3_aut0m4t3d_t00ls_l1k3_4n9r_0r_Z3_t0_m4k3_y0ur_l1f3_much_e4s13r.C0ngr4ts_f0r_s0lv1in9_th3_e4sy_ch4ll3ng3}

AIS3_crackme(Angr)

先看一下這支檔案在做甚麼
是簡單的 if-else 判斷

我們去看一下verify這個 function 在判斷甚麼

上面那些條件式全部都正確的話會return i==23
可以猜到長度應該是 23

script

from angr import *
from claripy import *

bin = './ais3_crackme'

p = Project(bin, auto_load_libs=False)

flag_chars = [BVS(f'flag_{i}',8) for i in range(100)]
flag = Concat(*flag_chars)

st = p.factory.entry_state(args=[bin,flag])

sm = p.factory.simgr(st)

sm.explore(find=lambda s: b'Correct' in s.posix.dumps(1),
        avoid=lambda s: b'sorry' in s.posix.dumps(1))

for s in sm.found:
    print(s.solver.eval(flag,cast_to=bytes))

flag ais3{I_tak3_g00d_n0t3s}


Author: Gunjyo
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint policy. If reproduced, please indicate source Gunjyo !
  TOC