4
[NPC2CTF 2025]esrever
main函數無法反匯編,一片紅,發現輸出的right和wrong在前面,input flag在后面,是將匯編反著來的


可能是在校驗flag的格式




兩個兩個換位
這個題能夠純猜出來,好像前面有函數能夠控制順序,所以也算是smc吧
感覺動調會更簡單,但是我的環境不允許
[NPC2CTF 2025]ugly_world
很多算數函數(ai都能識別),感覺和UIUC2024 Summarize差不多,但是要復雜很多

這里就是一個循環的內容
v9 = ((a[1] >> 1) + int32_1) ^ (a[1] + hex) ^ (int32_0 + (a[1] >> 1))
a[2] = v9 + a[0]//有問題
v17 = (int32_3 + (a[2] >> 1)) ^ (a[2] + hex) ^ (int32_2 + (a[2]) >> 1)
a[2] = a[1] + v17//有問題
這里可以猜出來是tea系列的,對比加密,hex就是delta,每一輪都不一樣,sum從0開始加delta
學到了,用python腳本去提取數據
import re
def extract_hex_numbers(code_text):
"""
提取代碼中所有0x開頭的十六進制數
:param code_text: 輸入的代碼文本
:return: 找到的所有十六進制數列表
"""
# 使用正則表達式匹配所有0x開頭的十六進制數
hex_pattern = r'0x[0-9A-Fa-f]+u?'
hex_numbers = re.findall(hex_pattern, code_text)
return hex_numbers
if __name__ == "__main__":
# 讀取代碼文件
with open('your_code.txt', 'r') as f:
code = f.read()
# 提取所有十六進制數
hex_numbers = extract_hex_numbers(code)
# 打印結果
print("找到的所有十六進制數:")
for i, num in enumerate(hex_numbers, 1):
print(f"{i}. {num}")
輸出可以發現有128個數字,也就是循環了128輪
# import re
#
#
# def extract_hex_numbers(code_text):
# """提取代碼中所有0x開頭的十六進制數"""
# hex_pattern = r'0x[0-9A-Fa-f]+u?'
# return re.findall(hex_pattern, code_text)
#
#
# def extract_cycle_parameters(code_text):
# """提取循環相關參數"""
# results = {
# 'rol_shifts': [], # rol的位移參數
# 'sal_shifts': [] # sal_1的位移參數
# }
#
# lines = [line.strip() for line in code_text.split('\n') if line.strip()]
#
# for line in lines:
# if '= rol(' in line:
# parts = line.split('rol(')[1].split(')')[0].split(',')
# if len(parts) == 2:
# results['rol_shifts'].append(parts[1].strip())
#
# elif '= sal_1(' in line:
# parts = line.split('sal_1(')[1].split(')')[0].split(',')
# if len(parts) == 2:
# results['sal_shifts'].append(parts[1].strip())
#
#
# return results
#
#
# if __name__ == "__main__":
# with open('E:\\NSS\\your_code.txt', 'r') as f:
# code = f.read()
#
# # 提取所有參數
# hex_numbers = extract_hex_numbers(code)
# extracted = extract_cycle_parameters(code)
#
# # 單行逗號分隔輸出
# print("十六進制數:")
# print(','.join(hex_numbers))
#
# print("\nROL位移參數:")
# print(','.join(extracted['rol_shifts']))
#
# print("\nSAL位移參數:")
# print(','.join(extracted['sal_shifts']))
rol = [1,1,3,3,4,4,3,3,4,4,3,3,3,3,6,6,4,4,6,6,2,2,1,1,6,6,6,6,1,1,4,4,5,5,4,4,1,1,4,4,4,4,2,2,5,5,4,4,6,6,2,2,2,2,3,3,4,4,5,5,5,5,5,5,4,4,5,5,1,1,6,6,4,4,2,2,3,3,6,6,5,5,6,6,6,6,1,1,2,2,2,2,4,4,5,5,2,2,4,4,6,6,6,6,3,3,6,6,2,2,1,1,1,1,5,5,3,3,5,5,3,3,2,2,6,6,4,4,6,6,4,4,2,2,1,1,4,4,5,5,4,4,5,5,6,6,1,1,5,5,2,2,2,2,6,6,2,2,6,6,3,3,3,3,5,5,3,3,3,3,6,6,6,6,5,5,4,4,4,4,2,2,1,1,5,5,1,1,2,2,2,2,1,1,5,5,3,3,6,6,1,1,1,1,5,5,5,5,1,1,4,4,4,4,2,2,4,4,6,6,6,6,3,3,4,4,6,6,5,5,1,1,1,1,6,6,5,5,4,4,3,3,6,6,5,5,5,5,2,2,1,1,4,4,2,2]
sal = [1,1,4,4,6,6,6,6,1,1,2,2,3,3,3,3,6,6,3,3,2,2,5,5,6,6,2,2,5,5,4,4,5,5,6,6,3,3,4,4,2,2,3,3,4,4,2,2,3,3,3,3,2,2,2,2,4,4,6,6,4,4,2,2,2,2,4,4,1,1,3,3,4,4,2,2,4,4,1,1,1,1,5,5,1,1,1,1,5,5,5,5,4,4,5,5,2,2,1,1,4,4,3,3,1,1,6,6,5,5,3,3,1,1,5,5,4,4,4,4,2,2,1,1,1,1,6,6,1,1,3,3,5,5,6,6,5,5,2,2,4,4,3,3,2,2,3,3,6,6,1,1,3,3,3,3,6,6,2,2,4,4,2,2,4,4,1,1,4,4,3,3,2,2,3,3,6,6,5,5,5,5,5,5,4,4,6,6,5,5,1,1,2,2,3,3,6,6,5,5,6,6,5,5,4,4,2,2,6,6,2,2,5,5,1,1,6,6,1,1,4,4,6,6,6,6,3,3,2,2,6,6,2,2,6,6,2,2,3,3,5,5,1,1,1,1,6,6,4,4,2,2,4,4,3,3]
for i in range(0,len(rol),2):
print(rol[i],end=',')
print()
for i in range(0,len(rol),2):
print(sal[i],end=',')
提取其他參數
key也就是我用int32表達的數據是傳入的a2,可以直接提取dword
0x11223344,0x55667788,0x9900AABB,0xCCDDEEFF
key的取法都是1,0,3,2
rol與sal參數每次循環使用兩次且相同,密文為10個dword,對應循環5次的tea加密
#include <stdio.h>
#include <stdint.h>
int k[] = {0x11223344, 0x55667788, 0x9900AABB, 0xCCDDEEFF};
int sal[] = {1,4,6,6,1,2,3,3,6,3,2,5,6,2,5,4,5,6,3,4,2,3,4,2,3,3,2,2,4,6,4,2,2,4,1,3,4,2,4,1,1,5,1,1,5,5,4,5,2,1,4,3,1,6,5,3,1,5,4,4,2,1,1,6,1,3,5,6,5,2,4,3,2,3,6,1,3,3,6,2,4,2,4,1,4,3,2,3,6,5,5,5,4,6,5,1,2,3,6,5,6,5,4,2,6,2,5,1,6,1,4,6,6,3,2,6,2,6,2,3,5,1,1,6,4,2,4,3};
int rol[] = {1,3,4,3,4,3,3,6,4,6,2,1,6,6,1,4,5,4,1,4,4,2,5,4,6,2,2,3,4,5,5,5,4,5,1,6,4,2,3,6,5,6,6,1,2,2,4,5,2,4,6,6,3,6,2,1,1,5,3,5,3,2,6,4,6,4,2,1,4,5,4,5,6,1,5,2,2,6,2,6,3,3,5,3,3,6,6,5,4,4,2,1,5,1,2,2,1,5,3,6,1,1,5,5,1,4,4,2,4,6,6,3,4,6,5,1,1,6,5,4,3,6,5,5,2,1,4,2};
int delta[] = {0x3CA6F3E,0xF2E1C7F1,0x79A22843,0xD47FFC9D,0xDD10F4C,0x1DC368A1,0x11B15F8A,0x9469B3CD,0x45D6DB5F,0xBC6EE006,0xA76D8146,0xD542E337,0x242E1155,0xAA7F93DD,0x88625ECB,0x3738E499,0xCEF27BB0,0x134FF759,0x358CA57E,0x3461F310,0x28540EE7,0x81C0B176,0xF725EE9C,0xAF823A69,0x61E8ECB3,0xF4919548,0x6AF44E11,0x866162F3,0x867F7E65,0x6B26444C,0x10216241,0x9C1BA3CD,0x1268FEAD,0xF462B3B5,0x5F7DE761,0x72EAD5B6,0xFBCE0C75,0x44EF4142,0x54DCC3C0,0xAFFE805D,0xC8833729,0x3C944186,0x261169A,0xB547EA2F,0x9B499585,0xFE0190BF,0x1EC74BE7,0xAFC9292E,0xC32F4EEF,0x420A1A4,0x94BEAB2B,0xA0693238,0x4DD5ADC1,0x9F658F31,0x1732EA46,0x76BEE7DD,0x12C63095,0x9C202C7C,0xAC9BB4C4,0x1762AEAF,0xCA41991E,0xC0480F85,0xBF534431,0xF1C2780E,0x990A7D6F,0x69D22B81,0x34DDECDE,0x11ECD8F8,0x22BB55D2,0xFFA55B0,0x6CC1AFBF,0xA5610F61,0x13190C95,0xE09A5D29,0xE7514731,0x9AE21D7A,0xB8D90F5A,0x4C7299A9,0xC4FDB94E,0xA6475083,0xBFB62E5,0x8F7F77EB,0xDA2568BB,0x55C4DA9E,0xC2932973,0xCBC60B6D,0xC46720FD,0x2046D79D,0x629CBD81,0x932B1F48,0x72ED29C0,0xF4B566D3,0xCBC53B21,0x7836C87B,0xBA4357B1,0xCFD332E2,0x4D488FCB,0xA06DEFBF,0x68211846,0xC17F878D,0x33B10E2C,0xCFA0E756,0x4C3C0691,0x870BE107,0x55B3FAF0,0xFD39F8D7,0x4B9A7795,0x188CFA42,0xAA79A09D,0x620CF186,0xEFDE898A,0x2FA95D43,0xD67359DB,0x8625BC1B,0x7A1A3BBC,0xE6ECEF6C,0xBA27A5C6,0x559FE417,0xF01DF04D,0x3F910D52,0x382B7BE,0xAAECB195,0x2E440D8E,0xB3D58B0B,0x3CA704B8,0x63293098,0x714CFD4D,0x47C8D0F7};
void decrypt(int *v, int *k) {
int v0 = v[0], v1 = v[1];
int sum = 0;
for(int i = 0; i < 128; i++) {
sum += delta[i];
}
for(int i = 127; i >= 0; i--) {
v1 -= ((v0 << sal[i]) + k[2]) ^ (v0 + sum) ^ ((v0 >> rol[i]) + k[3]);
v0 -= ((v1 << sal[i]) + k[0]) ^ (v1 + sum) ^ ((v1 >> rol[i]) + k[1]);
sum -= delta[i];
}
v[0] = v0;
v[1] = v1;
}
int main() {
int v[10] = {
0xBD3BE58, 0xBE73BBFB, 0xC8C8AF4E, 0xB3C7D86,
0xC0257C09, 0x1D8FE0B0, 0x8837180C, 0xF5CF9D23,
0xB7A8B599, 0xAE630F3D
};
for(int i = 0; i < 5; i++) {
int temp[2] = {v[i*2], v[i*2+1]};
decrypt(temp, k);
for(int j = 0; j < 4; j++) {
char c = (temp[0] >> (j * 8)) & 0xFF;
printf("%c", c);
}
for(int j = 0; j < 4; j++) {
char c = (temp[1] >> (j * 8)) & 0xFF;
printf("%c", c);
}
}
return 0;
}
//flag{UG1y_T3A_m@k35_[m3]_fe31_NaU5Eou5!}
[NPC2CTF 2025]randomXor

這里面srand和rand函數都是自定義的


后續用這些函數生成的偽隨機數單字節異或加密
這樣的話就可以動調或者將函數復制出來
#include <stdio.h>
unsigned int mt[128];
unsigned short index1; //顯式表示__int16
void srand(int seed) {
mt[0] = seed;
for (int i = 1; i <= 0x71; ++i)
mt[i] = (-1482534043 * (mt[i - 1] ^ (mt[i - 1] >> 30)) + i) ^ 0x56;
index1 = 114;
}
int rand() {
if (index1 > 0x71) {
for (int i = 0; i <= 0x71; ++i) {
unsigned int v3 = ((mt[i] & 0x80000) | (mt[(i + 1) % 0x72] & 0x7FFFF)) >> 1;
if (mt[(i + 1) % 0x72] & 1)
v3 ^= 0x8908B0DF;
mt[i] = mt[(i + 514) % 0x72] ^ v3;
}
index1 = 0;
}
unsigned int v4 = mt[index1++];
unsigned int v5 = (v4 ^ (v4 >> 11) ^ (((v4 ^ (v4 >> 11)) << 7)) & 0x9D2C5680);//注意運算優先級的問題
return (v5 ^ ((v5 << 15) & 0xEFC60000)) ^ (((v5 ^ ((v5 << 15) & 0xEFC60000)) >> 18));
}
int main() {
char enc[] = {
0xCD,0xC7,0xE2,0x86,0x3A,0x19,0xB9,0xB6,0xF1,0x81,0x45,0xB4,0xB6,0xE5,0xD,0xD4,
0xB4,0xA6,0xD3,0xF7,0x33,0x5D,0x5F,0x9,0x95,0xAF,0x9A,0xBE,0x89,0xEA,0x54,0x71,
0x68,0xC6,0x8B,0x84,0x5,0x14,0xBB,0x41,0xDD,0x34,0x91,0x1B,0x21,0x83,0xDE,0x15,
0x52,0x22,0x8A,0xE1,0xBD,0x33,0x4D,0x7E,0xD2,0xA3,0xA9,0x12,0xF1,0xE9,0x88,0x60,
0x24,0xE6,0xAB,0x54,0xCF,0x2,0x1B,0x6B,0x6B,0xBA,0x26,0x9,0xFB,0x10,0x97,0xDF,
0x17,0xBF,0xCC,0xE7,0xB0,0x42,0xE5,0x32,0x4C,0xF,0xE0,0x60,0x47,0xD0,0x5A,0xE8,
0x48,0xAE,0x74,0x4D,0x98,0x7A,0xB3,0xD2,0xDE,0x1B,0x96,0x91,0x7A,0x3,0x67,0xCF,
0xF0,0x31,0x32,0x49,0x9A,0xE0,0xC2,0x3B,0x51,0x63,0xFF,0x84,0x60,0x5B,0xC1,0x8E
};
srand(114514);
for (int i = 0; i < 128; i++)
enc[i] ^= rand(); // XOR 解密
for (int i = 0; i < 128; i++)
printf("%c", (unsigned char)enc[i]);
return 0;
}
注意運算的優先級的問題,特別是我標注出來的那個地方,卡了很久就是因為那里
ida里面沒有用括號顯示出來,但是其實能看出來,而且ai能給的邏輯也是最后來異或的
[tgctf2025]randomsystem
sub_412370是主函數

這四個函數都有花
去花
先去第四個函數的花
sub_41105F

nop完方框內的

主函數里面傳入的參數只有兩個,Destination和v11

sub_411307
用nomoreflower腳本跑一下,再進入函數


按C強制轉換

sub_411334

call無意義的地址,就將call指令(E9)刪掉,如下圖

nop

sub_4112DA

00413113的E9也要nop


TlsCallback_0_0

__int64 __fastcall TlsCallback_0_0(int a1, int a2, int a3, int a4, int a5)
{
int v5; // eax
__int64 v7; // [esp-4h] [ebp-1FCh]
int v8; // [esp+0h] [ebp-1F8h]
int j; // [esp+D0h] [ebp-128h]
int i; // [esp+DCh] [ebp-11Ch]
int v11; // [esp+E8h] [ebp-110h]
_DWORD v12[65]; // [esp+F4h] [ebp-104h] BYREF
int savedregs; // [esp+1F8h] [ebp+0h] BYREF
v5 = v8;
Seed = 2025;
v12[0] = 1;
v12[1] = 1;
v12[2] = 0;
v12[3] = 1;
v12[4] = 0;
v12[5] = 0;
v12[6] = 1;
v12[7] = 0;
v12[8] = 0;
v12[9] = 1;
v12[10] = 1;
v12[11] = 0;
v12[12] = 0;
v12[13] = 1;
v12[14] = 0;
v12[15] = 1;
v12[16] = 0;
v12[17] = 0;
v12[18] = 1;
v12[19] = 1;
v12[20] = 0;
v12[21] = 1;
v12[22] = 1;
memset(&v12[23], 0, 16);
v12[27] = 1;
v12[28] = 0;
v12[29] = 1;
v12[30] = 0;
v12[31] = 1;
v12[32] = 0;
v12[33] = 1;
v12[34] = 0;
v12[35] = 0;
v12[36] = 1;
v12[37] = 0;
v12[38] = 1;
memset(&v12[39], 0, 24);
v12[45] = 1;
v12[46] = 0;
v12[47] = 1;
memset(&v12[48], 0, 24);
v12[54] = 1;
v12[55] = 1;
v12[56] = 0;
v12[57] = 1;
v12[58] = 1;
memset(&v12[59], 0, 16);
v12[63] = 1;
v11 = 0;
for ( i = 0; i < 8; ++i )
{
for ( j = 0; j < 8; ++j )
{
a2 = v12[v11];
dword_41C368[8 * i + j] = a2;
++v11;
}
v5 = i + 1;
}
sub_41120D(&savedregs, &dword_411B50, v5, a2);
return v7;
}
回到開頭
學習的是liv:https://tkazer.github.io/2025/04/13/TGCTF2025/index.html

a=[5,2,6,5,5,6,6,5,5,2,6,5,5,3,6,5]
for i in a:
print(f"{i:04b}",end='')
所以something應該是0101001001100101010101100110010101010010011001010101001101100101

轉為字符就是最后異或的key
#include <stdio.h>
int main() {
int v17[64] ={0};
v17[0] = 376;
v17[1] = 356;
v17[2] = 169;
v17[3] = 501;
v17[4] = 277;
v17[5] = 329;
v17[6] = 139;
v17[7] = 342;
v17[8] = 380;
v17[9] = 365;
v17[10] = 162;
v17[11] = 258;
v17[12] = 381;
v17[13] = 339;
v17[14] = 347;
v17[15] = 307;
v17[16] = 263;
v17[17] = 359;
v17[18] = 162;
v17[19] = 484;
v17[20] = 310;
v17[21] = 333;
v17[22] = 346;
v17[23] = 339;
v17[24] = 150;
v17[25] = 194;
v17[26] = 175;
v17[27] = 344;
v17[28] = 158;
v17[29] = 250;
v17[30] = 128;
v17[31] = 175;
v17[32] = 158;
v17[33] = 173;
v17[34] = 152;
v17[35] = 379;
v17[36] = 158;
v17[37] = 292;
v17[38] = 130;
v17[39] = 365;
v17[40] = 197;
v17[41] = 20;
v17[42] = 197;
v17[43] = 161;
v17[44] = 198;
v17[45] = 10;
v17[46] = 207;
v17[47] = 244;
v17[48] = 202;
v17[49] = 14;
v17[50] = 204;
v17[51] = 176;
v17[52] = 193;
v17[53] = 255;
v17[54] = 35;
v17[55] = 7;
v17[56] = 158;
v17[57] = 181;
v17[58] = 145;
v17[59] = 353;
v17[60] = 153;
v17[61] = 357;
v17[62] = 246;
v17[63] = 151;
char key[] = "ReVeReSe";
for(int i=0;i<64;i++){
printf("%d,",v17[i] ^ key[i%8]);
}
}//298,257,255,400,327,300,216,307,302,264,244,359,303,310,264,342,341,258,244,385,356,296,265,310,196,167,249,317,204,159,211,202,204,200,206,286,204,321,209,264,151,113,147,196,148,111,156,145,152,107,154,213,147,154,112,98,204,208,199,260,203,256,165,242
由于是矩陣乘法的運算,所以要先求逆矩陣
這個地方具體的先留一下
做之后的
https://rrefcalculator.top/zh/逆矩陣計算器/ (求逆矩陣)

https://www.lddgo.net/math/matrix-calculator(算乘法)

#include <stdio.h>
int main() {
int v17[64] ={102 , 100 , 49 , 49 , 118 , 53 , 54 , 100,
52 , 53 , 52 , 114 , 54 , 102 , 52 , 97 ,
99 , 98 , 45 , 49 , 101 , 97 , 56 , 100,
45 , 54 , 102 , 121 , 56 , 48 , 55 , 57 ,
53 , 97 , 102 , 56 , 51 , 122 , 102 , 114,
98 , 56 , 45 , 99 , 100 , 54 , 99 , 100,
99 , 50 , 52 , 116 , 99 , 97 , 55 , 53 ,
53 , 57 , 102 , 97 , 48 , 57 , 57 , 45 };
for(int i=0;i<64;i++){
printf("%c",v17[i]);
}
}//fd11v56d454r6f4acb-1ea8d-6fy80795af83zfrb8-cd6cdc24tca7559fa099-
回調函數里面seed=2025
#include <stdint.h>
int main() {
srand(2025);
for (int i = 0; i < 1000; i++) {
printf("%d,",(rand())%32);
}
return 0;
}//27, 26, 25, 23, 28, 1, 6, 10, 20, 7, 15, 14, 31, 18, 19, 21, 9, 30, 22, 24, 8, 2, 29, 3, 12, 11, 17, 0, 13, 16, 4, 5
ai協助去重復的內容
按照這個順序就可以恢復了
#include <stdio.h>
int main() {
int a[]={27, 26, 25, 23, 28, 1, 6, 10, 20, 7, 15, 14, 31, 18, 19, 21, 9, 30, 22, 24, 8, 2, 29, 3, 12, 11, 17, 0, 13, 16, 4, 5};
char flag[]="fd11v56d454r6f4acb-1ea8d-6fy80795af83zfrb8-cd6cdc24tca7559fa099-";
for(int i=0;i<32;i++){
char temp =0;
temp = flag[i];
flag[i] = flag[64 - a[i]-1];
flag[64 - a[i]-1] = temp;
}
printf("%s",flag);
}//3zfb899ac5c256d-7a8r59f0tcc-4daf6b8vfd111-a44ff04r8-6dce5697da5y

浙公網安備 33010602011771號