因為是一年前隨手記錄的東西所以稍微有點雜 ><
CTFd
Practice
picoCTF 2019 asm2
What will asm2(0x6,0x24) return?
asm2:
<+0>: push ebp
<+1>: mov ebp,esp
<+3>: sub esp,0x10
<+6>: mov eax,DWORD PTR [ebp+0xc]
<+9>: mov DWORD PTR [ebp-0x4],eax
<+12>: mov eax,DWORD PTR [ebp+0x8]
<+15>: mov DWORD PTR [ebp-0x8],eax
<+18>: jmp 0x50c
<+20>: add DWORD PTR [ebp-0x4],0x1
<+24>: add DWORD PTR [ebp-0x8],0xaf
<+31>: cmp DWORD PTR [ebp-0x8],0xa3d3
<+38>: jle 0x501
<+40>: mov eax,DWORD PTR [ebp-0x4]
<+43>: leave
<+44>: ret
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
import java.util.Arrays;
import java.util.Base64;
//
// Decompiled by Procyon v0.5.36
//
public class problem
{
public static String get_flag() {
final String s = "eux_Z]\\ayiqlog`s^hvnmwr[cpftbkjd";
final String s2 = "Zf91XhR7fa=ZVH2H=QlbvdHJx5omN2xc";
final byte[] bytes = s.getBytes();
final byte[] bytes2 = s2.getBytes();
final byte[] array = new byte[bytes2.length];
for (int i = 0; i < bytes2.length; ++i) {
array[i] = bytes2[bytes[i] - 90];
}
System.out.println(Arrays.toString(Base64.getDecoder().decode(array)));
return new String(Base64.getDecoder().decode(array));
}
public static void main(final String[] array) {
System.out.println("Nothing to see here");
}
}
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 檔
所以去執行看看,會發現是猜數字的程式碼
我們可以去看一下它的 asmobjdump -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 (偽代碼)
int __cdecl main(int argc, const char **argv, const char **envp)
{
int n; // [rsp+Ch] [rbp-14h]
int i; // [rsp+10h] [rbp-10h]
int m; // [rsp+14h] [rbp-Ch]
unsigned __int64 v7; // [rsp+18h] [rbp-8h]
v7 = __readfsqword(0x28u);
__isoc99_scanf(&unk_A64, &n, envp);
f[30] = 160LL;
f[10] = 47LL;
f[13] = 4LL;
f[25] = 205LL;
f[5] = 87LL;
f[24] = 247LL;
f[6] = 76LL;
f[31] = 176LL;
f[7] = 74LL;
f[34] = 154LL;
f[21] = 231LL;
f[32] = 135LL;
f[8] = 75LL;
f[1] = 102LL;
f[9] = 75LL;
f[28] = 232LL;
f[29] = 148LL;
f[3] = 108LL;
f[11] = 33LL;
f[4] = 127LL;
f[14] = 21LL;
f[18] = 89LL;
f[16] = 3LL;
f[26] = 215LL;
f[20] = 211LL;
f[15] = 8LL;
f[17] = 25LL;
f[27] = 217LL;
f[0] = 101LL;
f[33] = 143LL;
f[22] = 245LL;
f[19] = 241LL;
f[12] = 56LL;
f[36] = 129LL;
f[23] = 206LL;
f[2] = 125LL;
f[35] = 202LL;
m = n ^ 0x58EB29;
for ( i = 0; i <= 36; ++i )
g[i] = m * i ^ (unsigned __int64)f[i];
g[i] = 0;
if ( g[0] == 101 && g[1] == 97 && g[2] == 115 && g[3] == 121 && g[4] == 99 && g[5] == 116 && g[6] == 102 )
printf("the flag is %s\n", g);
return 0;
}
#include <bits/stdc++.h>
using namespace std;
int f[40];
int main(){
f[30] = 160LL;
f[10] = 47LL;
f[13] = 4LL;
f[25] = 205LL;
f[5] = 87LL;
f[24] = 247LL;
f[6] = 76LL;
f[31] = 176LL;
f[7] = 74LL;
f[34] = 154LL;
f[21] = 231LL;
f[32] = 135LL;
f[8] = 75LL;
f[1] = 102LL;
f[9] = 75LL;
f[28] = 232LL;
f[29] = 148LL;
f[3] = 108LL;
f[11] = 33LL;
f[4] = 127LL;
f[14] = 21LL;
f[18] = 89LL;
f[16] = 3LL;
f[26] = 215LL;
f[20] = 211LL;
f[15] = 8LL;
f[17] = 25LL;
f[27] = 217LL;
f[0] = 101LL;
f[33] = 143LL;
f[22] = 245LL;
f[19] = 241LL;
f[12] = 56LL;
f[36] = 129LL;
f[23] = 206LL;
f[2] = 125LL;
f[35] = 202LL;
for(int i=0 ; i<37 ; i++) cout<<f[i]<<" , ";
return 0;
}
得到 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
flag
BreakALLCTF{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(先進後出),所以順序是由底端到頂端
flag
MyFirstCTF{C0mpi1e_aSm_4nd_RuN!}
Level 2
林思辰_base64
把我們找到的那一串奇怪的字串拿去 base64 decode
發現是push
flag
MyFirstCTF{Y0U_FlnD_m4G1c_StRinG!!!}
林思辰_encrypt
丟進去 IDA Pro 看看
我們要做的事情是”找出加密的方法並解密一個特別的字串”
稍微美化一下 item 名稱之後看一下這個程式碼在做甚麼
可以看到輸入的 39 個字會依照 ASCII 數值被拆成 3 種
- 1-31 || 127 :
+0
-> 1-31 || 127 - 32-81 :
+45
-> 77-126 - 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??!!}
print("".join(map(lambda i : chr((i[0] + 32) ^ i[1]) , enumerate([i for i in a if i != 0x00]))))
description
先創一個 []
裡面把所有原先的 array 的 0 去掉
然後用 enumerate()
去產數字跟迭代陣列 => (0 , array[0]) => (1 , array[1])
產完利用 map()
把上面的 enumerate()
丟進去 lambda function
取 數字跟陣列內容出來做運算然後轉 chr
再用 "".join
把結果的陣列全部串起來
林思辰_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}