ez_pyyy
pyc反编译,加密顺序是,异或17,高低位交换,反转字节,循环左移32位
SYC{jtfgdsfda554_a54d8as53}
cipher = [
48, 55, 57, 50, 53, 55, 53, 50, 52, 50, 48, 55, 101, 52, 53, 50, 52, 50, 52, 50, 48, 55, 53, 55, 55, 55, 50, 54, 53, 55, 54, 55, 55, 55, 53, 54, 98, 55, 97, 54, 50, 53, 56, 52, 50, 52, 99, 54, 50, 50, 52, 50, 50, 54]
def en3(b):
return (b << 4 & 240) | (b >> 4 & 15)
def en33_inv(data, n):
bit_len = len(data) * 8
n = n % bit_len
val = int.from_bytes(data, 'big')
val = (val >> n) | (val << (bit_len - n)) & ((1 << bit_len) - 1)
return val.to_bytes(len(data), 'big')
cipher_hex = ''.join(chr(c) for c in cipher)
data = bytes.fromhex(cipher_hex)
data = en33_inv(data, 32)
data = data[::-1]
data = bytes([en3(b) for b in data])
data = bytes([b ^ 17 for b in data])
flag = data.decode('utf-8')
print(flag)
only flower
ida反编译打开找到jumpout处打开汇编,发现是jmp跳转到错误地址导致错误,jmp对应ef,将ef部分nop掉,直到能看到正确伪代码,查看算法得出(试出来的算法,试了几个不同rol8的实现,标准循环左移,右移,右移成功了)
cipher = [
0x0A, 0x84, 0xC2, 0x84, 0x51, 0x48, 0x5F, 0xF2,
0x9E, 0x8D, 0xD0, 0x84, 0x75, 0x67, 0x73, 0x8F,
0xCA, 0x57, 0xD7, 0xE6, 0x14, 0x6E, 0x77, 0xE2,
0x29, 0xFE, 0xDF, 0xCC
]
key = "GEEK2025"
result = []
for i, y in enumerate(cipher):
r = (y - i) & 0xFF
k = ord(key[i % len(key)])
shift = k & 7
x = ((r >> shift) | (r << (8 - shift))) & 0xFF
result.append(chr(x ^ k))
print(''.join(result))
SYC{asdjjasdhjk12wk12ijkejk}
QYQSの奇妙冒险
die查看文件格式,拖进x86dbg查看,题目提示有按空格,试了下发现叫我nop的,把jmp部分nop结束运行,有多余的int3部分,nop掉进入正确汇编码,继续运行,随机试一个发现退出了,放弃了,拖进ida静态分析发现是xor,直接算了,就是先让input与i异或,再与key[i%4]异或,key为QYQS
def decrypt():
QYQS = [
2, 1, 16, 43, 28, 3, 23, 57, 6, 1,
34, 41, 14, 11, 45, 109, 6, 32, 23, 127, 56
]
key = "QYQS"
result = []
for i in range(21):
decrypted = QYQS[i] ^ ord(key[i % 4])
decrypted ^= i
result.append(chr(decrypted))
return ''.join(result)
flag = decrypt()
print(f"Flag: {flag}")
SYC{I_@m_QyqS_r1GhT?}
encode
拖进ida,有个base64提示,查看顺序表发现是标准base64,外加一个异或,(每个与0x5A异或)把密文解码发现是乱码,不对,翻翻别的算法,发现还有个xtea,加上xtea解码,密钥是geek2025reverse!,得出flag
流程就是先用tea加密,异或,base64加密得到加密后flagvBzX30Koxl3HpDaYaFJKhyB/1ckuVCnc4wZhrwUWeNuZkAxr+Qn5UaYbpvymmCrk
import base64
import struct
def xtea_dec(block, key):
v0, v1 = struct.unpack('>II', block)
sum_val, delta = 0xC6EF3720, 0x9E3779B9
for _ in range(32):
v1 = (v1 - (((v0 << 4) ^ (v0 >> 5)) + v0 ^ sum_val + key[(sum_val >> 11) & 3])) & 0xFFFFFFFF
sum_val = (sum_val - delta) & 0xFFFFFFFF
v0 = (v0 - (((v1 << 4) ^ (v1 >> 5)) + v1 ^ sum_val + key[sum_val & 3])) & 0xFFFFFFFF
return struct.pack('>II', v0, v1)
data = base64.b64decode("vBzX30Koxl3HpDaYaFJKhyB/1ckuVCnc4wZhrwUWeNuZkAxr+Qn5UaYbpvymmCrk")
data = bytes(b ^ 0x5A for b in data)
key = struct.unpack('>4I', b"geek2025reverse!")
res = b''.join(xtea_dec(data[i:i+8], key) for i in range(0, len(data), 8))
print(res[:-res[-1]].decode())
SYC{St4nd4rd_Funct10n_N0t_4lw4ys_St4nd4rd}
ezSMC
去掉virtualprotcet部分,在miao encrypt点进去之后的前面下断点动调,得到解密后的加密函数内容,u,c得到伪代码,算法是rc4+base58+base64
import base64
BASE58_TABLE = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz123456789"
class RC4:
def __init__(self, key):
self.S = list(range(256))
j = 0
for i in range(256):
j = (j + self.S[i] + key[i % len(key)]) & 0xFF
self.S[i], self.S[j] = self.S[j], self.S[i]
self.i = 0
self.j = 0
def crypt(self, data):
res = bytearray()
for b in data:
self.i = (self.i + 1) & 0xFF
self.j = (self.j + self.S[self.i]) & 0xFF
self.S[self.i], self.S[self.j] = self.S[self.j], self.S[self.i]
k = self.S[(self.S[self.i] + self.S[self.j]) & 0xFF]
res.append(b ^ k)
return bytes(res)
def base58_decode(data):
leading_zeros = 0
for char in data:
if char == BASE58_TABLE[0]:
leading_zeros += 1
else:
break
num = 0
for char in data[leading_zeros:]:
num = num * 58 + BASE58_TABLE.index(char)
res = bytearray()
while num > 0:
res.append(num & 0xFF)
num >>= 8
return (b'\x00' * leading_zeros) + res[::-1]
cipher = "tHMoSoMX71sm62ARQ8aHF6i88nhkH9Ac2J7CrkQsQgXpiy6efoC8YVkzZu1tMyFxCLbbqvgXZHxtwK5TACVhPi1EE5mK6JG56wPNR4d2GmkELGfJHgtcAEH7"
b58_res = base58_decode(cipher)
b64_res = base64.b64decode(b58_res)
hex_res = bytes.fromhex(b64_res.decode())
rc4 = RC4([17])
flag = rc4.crypt(hex_res)
print(flag.decode())
SYC{OHhhhhhhh_y0u_Kn0m_SMCCCC@!}
QYQSの奇妙冒险2
翻汇编中,看到flag了,把flag导出来去空格
SYC{M@y_bE_y0u_F1nd?}
obfuscat3
在init_encode里面看到一个像是密钥流一样的东西,仔细看发现是rc4,v5 = 0x617261736D6153LL,对应Samsara,main里面有
obf_encode(s, n_4, (unsigned __int8 *)&v5);
a1[i] += mysterious_box[(unsigned __int8)((int)(v19
- ((~(unsigned __int8)mysterious_box[v22] | ~((v13 & 0x7911131C | mysterious_box[v21] & 0xE3) ^ (mysterious_box[v22] & 0x1C | ~(unsigned __int8)mysterious_box[v22] & 0x86EEECE3)))
+ 1))
% 256)];
(能看到类似rc4的操作了)在initencode里·,初始化了s,用密钥置换,obfencode生成密钥流,操作,拿rc4解出错了,重新看,使用了mysteriousbox数组,发现是变种rc4,异或变成加法,
a1[i] += mysterious_box
解密把加法变成减法
def rc4_init(key):
S = list(range(256))
j = 0
for i in range(256):
j = (j + S[i] + key[i % len(key)]) % 256
S[i], S[j] = S[j], S[i]
return S
def rc4_stream(S, length):
i = 0
j = 0
stream = []
for _ in range(length):
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
stream.append(S[(S[i] + S[j]) % 256])
return stream
cipher = [
0xB4, 0xCD, 0x69, 0x54, 0xBD, 0x67, 0x20, 0x9D, 0xF2, 0xC3, 0x24, 0x14, 0xC2, 0x1B, 0xE9, 0x6A,
0x44, 0x14, 0x4E, 0x39, 0xC5, 0xC8, 0x5B, 0x11, 0x75, 0xAD, 0xDE, 0xBB, 0xFE, 0xE4, 0x6E, 0x65,
0x06, 0x9A, 0x91, 0xFE, 0xA0, 0x68, 0xA4, 0x86, 0x17, 0x6C, 0x0A, 0xCF, 0x1E, 0x67, 0xE3, 0x0D,
0x60, 0x47, 0x13, 0x6B, 0xD1, 0x36, 0xF2, 0x77, 0x58, 0x76, 0x1E, 0x98, 0xF5, 0x7F, 0x0A, 0x92,
0xB7, 0x0A, 0xEA, 0xAE, 0x46, 0x7E, 0x6A, 0x18, 0x4A, 0x59, 0x4E, 0x71, 0xB2, 0xE1, 0x41, 0x7A,
0x0B, 0x31, 0xBA, 0xC6, 0xAA, 0xCF, 0xCE, 0x09, 0xBF, 0x2E, 0xF8, 0x4D, 0x75, 0xEF, 0x14, 0xED,
0x5F, 0x66, 0x44, 0x6F, 0xDE, 0xE2, 0x7C, 0x10, 0x8C, 0xB7, 0x4E, 0x6B, 0xB2, 0xD4, 0xF6, 0x91,
0xD7, 0x84, 0x86, 0x1F, 0xF8, 0x65, 0x94, 0x0B, 0x14, 0x28, 0xFB, 0xDD, 0x47, 0xF4, 0xC1, 0x17,
0x42, 0x3F, 0x1E, 0x38, 0x07, 0xBB, 0x37, 0x33, 0x12, 0x0C, 0x16, 0x68, 0xE0, 0x23, 0x12, 0x75,
0x72, 0xD9, 0x71, 0x7A, 0x88, 0xD0, 0x46, 0x28, 0x88, 0xAD, 0x1E, 0x98, 0x8F, 0x92, 0x7E, 0x0E,
0x69, 0x29, 0x37, 0xB1, 0xFF, 0xC5, 0xAF, 0x6F, 0x41, 0x37, 0x65, 0x0E, 0xD2, 0x62, 0x11, 0x8F,
0xA6, 0x3E, 0x95, 0xF5, 0x80, 0x9A, 0xDC
]
key = b'Samsara'
S = rc4_init(key)
stream = rc4_stream(S, len(cipher))
plain = bytes((cipher[i] - stream[i]) % 256 for i in range(len(cipher)))
print(plain.decode())
SYC{Alright_I_sti1l_h0pe_th3t_you_solved_the_chall3nge_by_deobfuscating_them_Geek_is_just_the_first_step_of_your_CTF_journey_Im_glad_I_could_be_part_of_your_growth_Good_luck_for_y0u!}
Gensh1n
有个简单输入,对应八个有一个相同,通过is valid char判断,将输入的每个字符与global_nodes[16 * j]比较,有匹配就设置v5=1跳出循环clean up里面,取八个字符作为v7,然后判断
if ( !validate_key((__int64)v7, 8) )
exit(1);
,在data段找到 arr geek2025,和result28字节数据,在sub44656里面看出rc4,因为有个sbox和ksa和prga和异或加密,普通rc4解密,解一下
validate_key说明globalnodes的八字节key固定
result = [0x52, 0x59, 0xF3, 0x8A, 0x00, 0x0F, 0xE6, 0x56, 0x36, 0xE5, 0xF0, 0x33, 0x40, 0x6E, 0x56, 0x81, 0x5A, 0xE5, 0x6F, 0x87, 0x6F, 0x9F, 0x21, 0xC9, 0xA6, 0xBB, 0x16, 0x51]
key = b"geek2025"
S = list(range(256))
j = 0
for i in range(256):
j = (j + S[i] + key[i % 8]) % 256
S[i], S[j] = S[j], S[i]
i = j = 0
plaintext = []
for byte in result:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
k = S[(S[i] + S[j]) % 256]
plaintext.append(byte ^ k)
print("Snd input:", bytes(plaintext))
SYC{50_y0u_pl@y_Gensh1n_too}
GeekBinder
获取硬编码数据,查看算法,有个8字节循环密钥,异或解密就行,两个文件分别打开使用的数据会有不同flag,有细微差别
在sub1119里,有一个xor的过程,每个字节,密钥是geek2025,循环使用,在qword2020,2928到2060,word2078,byte207a那里提数据,在内存中,字节从低地址到高地址,所以最后根据提取出的数据写解密脚本
但是第一个解密脚本得出了一个错误flag,格式是正确的
encrypted = [
0x34, 0x3C, 0x26, 0x10, 0x73, 0x5E, 0x72, 0x7C,
0x1E, 0x1F, 0x54, 0x05, 0x55, 0x6F, 0x66, 0x5D,
0x54, 0x3A, 0x15, 0x19, 0x5D, 0x53, 0x01, 0x46,
0x14, 0x56, 0x14, 0x34, 0x70, 0x03, 0x66, 0x42,
0x02, 0x00, 0x0B, 0x34, 0x74, 0x59, 0x5E, 0x50,
0x54, 0x3A, 0x54, 0x18, 0x6D, 0x53, 0x5D, 0x5B,
0x13, 0x17, 0x25, 0x19, 0x4B, 0x6F, 0x66, 0x5A,
0x38, 0x0B, 0x55, 0x19, 0x5F, 0x70, 0x5E, 0x6A,
0x17, 0x17, 0x25, 0x08, 0x46, 0x59, 0x51, 0x06,
0x38, 0x54, 0x0B, 0x34, 0x60, 0x55, 0x6D, 0x50,
0x09, 0x02, 0x54, 0x05, 0x57, 0x55, 0x40, 0x04,
0x09, 0x02,
0x18
]
key = "geek2025"
key_bytes = [ord(c) for c in key]
decrypted = []
for i, byte in enumerate(encrypted):
k = key_bytes[i % len(key_bytes)]
decrypted.append(byte ^ k)
decrypted_str = ''.join(chr(b) for b in decrypted)
print(decrypted_str)
SYC{An@Iyz1ng_Th3_proc3s3q_B3Tween_File3_1s_contr@ry_To_n0rm@l_pr@ctic3_1n_Re_engineer1ng},查看另一个so文件看到的是
*v3 = 0x7C725E7310263C34LL;
v3[1] = 0x5D666F5505541F1ELL;
v3[2] = 0x4601535D19153A54LL;
v3[3] = 0x4266037034165614LL;
v3[4] = 0x505E5974340B0002LL;
v3[5] = 0x5B5D536D18543A54LL;
v3[6] = 0x5A666F4B19251713LL;
v3[7] = 0x6A5E705F19550B38LL;
v3[8] = 0x651594608251717LL;
v3[9] = 0x506D5560340B5438LL;
v3[10] = 0x440555705540209LL;
换了个数据提,出正确flag了
encrypted = [
0x34, 0x3C, 0x26, 0x10, 0x73, 0x5E, 0x72, 0x7C,
0x1E, 0x1F, 0x54, 0x05, 0x55, 0x6F, 0x66, 0x5D,
0x54, 0x3A, 0x15, 0x19, 0x5D, 0x53, 0x01, 0x46,
0x14, 0x56, 0x14, 0x34, 0x70, 0x03, 0x66, 0x42,
0x02, 0x00, 0x0B, 0x34, 0x74, 0x59, 0x5E, 0x50,
0x54, 0x3A, 0x54, 0x18, 0x6D, 0x53, 0x5D, 0x5B,
0x13, 0x17, 0x25, 0x19, 0x4B, 0x6F, 0x66, 0x5A,
0x38, 0x0B, 0x55, 0x19, 0x5F, 0x70, 0x5E, 0x6A,
0x17, 0x17, 0x25, 0x08, 0x46, 0x59, 0x51, 0x06,
0x38, 0x54, 0x0B, 0x34, 0x60, 0x55, 0x6D, 0x50,
0x09, 0x02, 0x54, 0x05, 0x57, 0x55, 0x40, 0x04,
0x09, 0x02,
0x18
]
key = "geek2025"
key_bytes = [ord(c) for c in key]
decrypted = []
for i, byte in enumerate(encrypted):
k = key_bytes[i % len(key_bytes)]
decrypted.append(byte ^ k)
decrypted_str = ''.join(chr(b) for b in decrypted)
print(decrypted_str)
SYC{An@Iyz1ng_Th3_proc3ss3q_B3Tween_File3_1s_contr@ry_To_n0rm@l_pr@ctic3_1n_Re_eng1neer1ng}
ez_vm
sub_1a2b3c里,key为3,运行string_process_program,处理加密数据
sub_1a2b3c(global_vm, &sub_5c6d7e, 3LL, 0x1DuLL);
传入3了,后面数据变化了,
在sub_9e8f7a里,会读输入,将输入存到vm内存偏移512的地方,再将一段长度为29的数据从偏移256出复制到768处,在汇编码里面有一个mov r3, 0x5A,把z放入寄存器了,然后在vmrun里面执行了,判断异或在于10h,xor的操作码
提取数据,每个字节+3,与0x5A进行异或,得到flag
def solve_final():
encrypted_data = [
0x06, 0x00, 0x16, 0x1E, 0x0A,
0x66, 0x68, 0x36, 0x67, 0x34, 0x66,
0x02, 0x2B, 0x67, 0x02, 0x25, 0x66,
0x17, 0x68, 0x02, 0x25, 0x66, 0x29,
0x3C, 0x25, 0x26, 0x3C, 0x78, 0x24
]
flag = ""
for b in encrypted_data:
val = ((b + 3) & 0xFF) ^ 0x5A
flag += chr(val)
print(f"Flag: {flag}")
if __name__ == "__main__":
solve_final()
SYC{W31c0m3_t0_r3@1_r3verse!}
reReverse
打开main发现很简短,查看其他function发现了一个没见过的writtenflags,在csdn里面搜索发现应该是tf,查看其它部分,直接动调试验一个flag,发现符合tf直接被退出了,设置断点也会退出,搜索教程nop掉tf部分发现程序会崩溃,改去汇编里面找,在汇编里面发现有个tea系列的Δ常数0x9E3779B9,TEA算法的主要特征表现在sum和delta变量,有位运算和循环,尝试了tea和xtea都是乱码,没招了问了学长,对比tea,xtea,xxtea特征,发现mx,确定是xxtea。找到key,密钥,密文等部分,别的值解密是乱码没有数字,但是汇编解密有一段0000000000403080从这里开始,可能是比较的明文,从汇编码提出值,然后根据地址的顺序排列这些值0xDEAD, 0xBEEF, 0x5A7D, 0xC0FF运用密钥,最后解密成字符串
import struct
def xxtea_decrypt(v, k):
n = len(v)
rounds = 6 + 52 // n
sum_val = (rounds * 0x9E3779B9) & 0xFFFFFFFF
y = v[0]
for _ in range(rounds):
e = (sum_val >> 2) & 3
for p in range(n - 1, 0, -1):
z = v[p - 1]
y = v[p] = (v[p] - ((((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4))) ^ ((sum_val ^ y) + (k[(p & 3) ^ e] ^ z)))) & 0xFFFFFFFF
p = 0
z = v[n - 1]
y = v[0] = (v[0] - ((((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4))) ^ ((sum_val ^ y) + (k[(p & 3) ^ e] ^ z)))) & 0xFFFFFFFF
sum_val = (sum_val - 0x9E3779B9) & 0xFFFFFFFF
return v
data = [
0x2973BD37, 0x1BA99AA3, 0xB3C20088, 0xBFC393AB, 0x352ADCCF,
0x3B98E6E6, 0xAE421991, 0xD7B702CF, 0x0EEF6889, 0x08662435
]
key = [0xDEAD, 0xBEEF, 0x5A7D, 0xC0FF]
res = xxtea_decrypt(data, key)
flag_bytes = b''.join(struct.pack('<I', x) for x in res)
print(f"Hex: {flag_bytes.hex()}")
print(f"结果: {flag_bytes.decode().rstrip(chr(0))}")
在.text段可以看到比较指令
.text:00000000004008BA cmp r9d, 2973BD37h
.text:00000000004008E1 cmp r10d, 8662435h
.text:00000000004008ED cmp r11d, 0EEF6889h
.text:00000000004008F9 cmp ebx, 0AE421991h
.text:0000000000400902 cmp ebp, 0D7B702CFh
.text:000000000040090A cmp r8d, 3B98E6E6h
.text:0000000000400926 cmp edx, 352ADCCFh
.text:000000000040092F cmp ecx, 0BFC393ABh
.text:0000000000400938 cmp esi, 0B3C20088h
.text:0000000000400942 cmp edi, 1BA99AA3h
然后再这段中,有
.text:0000000000400CEA mov r9d, [rsp+40h]
.text:0000000000400CDE mov edi, [rsp+44h]
.text:0000000000400CD0 mov esi, [rsp+48h]
.text:0000000000400CC4 mov ecx, [rsp+4Ch]
.text:0000000000400CB4 mov edx, [rsp+50h]
.text:0000000000400CA7 mov r8d, [rsp+54h]
.text:0000000000400CA3 mov ebx, [rsp+58h]
.text:0000000000400C9F mov ebp, [rsp+5Ch]
.text:0000000000400C92 mov r11d, [rsp+60h]
.text:0000000000400C8D mov r10d, [rsp+64h]
加载值到寄存器的过程,然后在后面的比较里被使用
就是先从栈加载解密后的值到寄存器,再将寄存器值与硬编码比较,比较成功就win
SYC{sakurakouji_runasama_wa_seikai_ichi}
ezRu3t
下了个rust的插件,算法一个base64一个base85,有
!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstu
base85
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
base64
<AA;XAM?,_@;T[r@7E779h8;s>'`pt=>3c6ASuHFASOtP<Gkf_A4&gPAl1]S
密文
网站在线解密得SYC{Ohjhhh_y0u_g3t_Ezzzzz3_Ru3t!@}
qyqs2
反调试混淆技巧
浮点数标准(IEEE 754)NAN的特殊性质
.text:000000014001264B movss xmm0, [rbp+2D0h+a] ; 将变量 a 加载到 xmm0 寄存器
.text:0000000140012653 ucomiss xmm0, [rbp+2D0h+a] ; 将 xmm0 与 a 进行比较 (即比较 a 和 a)
.text:000000014001265A jp loc_1400127AA ; jp (Jump if Parity) 如果 P/PF 标志位为 1 则跳转
.text:0000000140012660 jnz loc_1400127AA ; jnz 如果非零则跳转(这里是辅助判断)
.text:0000000140012666 mov [rbp+2D0h+i], 0 ; 假路径:如果没跳转,继续执行这里
指令ucomiss
当两个操作数至少有一个是NAN时,比较结果会被标记为无需,三个标志位zf,pf,cf同时置为一。jp跳转检测pf,整数运算中,pf表示就行,pf设置为一,jp生效,跳转到loc_1400127AA
原理,ida生成伪代码时会进行死代码消除,ucomiss之后的jp或jnz分支被认为不可能执行
解决,将jp改为jmp强制跳转
her
enc1到enc2的连接点就是seh结构化异常处理,将异常处理函数地址压栈,保留旧的异常链表头,将当前栈顶设为新的表头,然后再mov large fs:0, esp后面,接了一个div,首先在xor ecx, ecx这里,将ecx寄存器清零,eax设为1,div 一个为0的寄存器,导致异常,然后将eip指向sub401186,让这几个无法执行
.text:00401F7C mov eax, [esp+0E0h+var_E0]
.text:00401F7F mov large fs:0, eax
.text:00401F85 add esp, 8
然后就到enc2了,继续找enc就行,就是把正常加密放进seh里面了,但seh的大体结构是不变的,在反调试的部分里面,因为设置了动态key,(每次触发异常的时候,进入enc2或者enc3,key就变化)所以把反调试改掉会直接出来空的
def solve():
enc = [
0x2D, 0x4F, 0x69, 0x3D, 0x5F, 0x01, 0xBD, 0x9F,
0xA4, 0x6D, 0x89, 0xAE, 0x2A, 0xEA, 0xD1, 0x9C,
0x71, 0x6D, 0xE1, 0x1E, 0x38, 0x7E, 0x8C, 0x0A,
0xCE, 0x6B, 0xE0, 0xF7, 0x36, 0x72, 0x99
]
b = 0
flag = ""
for i in range(len(enc)):
target_byte = enc[i]
b_start = b
found = False
for char_code in range(128):
curr_b = b_start
x = char_code
curr_b ^= 0x1A373
curr_b = (curr_b + 1) & 0xFFFFFFFF
x = (curr_b & 0xFF) ^ x ^ 0xAA
curr_b ^= 0x1A373
curr_b = (curr_b + 1) & 0xFFFFFFFF
term = (curr_b & 0xFF) + (i * i)
x = (x + term) & 0xFF
curr_b ^= 0x1A373
curr_b = (curr_b + 1) & 0xFFFFFFFF
curr_b ^= 0x1A373
curr_b = (curr_b + 1) & 0xFFFFFFFF
term = (curr_b & 0xFF) + (i * i)
x = (x + term) & 0xFF
out = ((x >> 5) | (x << 3)) & 0xFF
curr_b ^= 0x1A373
curr_b = (curr_b + 1) & 0xFFFFFFFF
curr_b ^= 0x1A373
curr_b = (curr_b + 1) & 0xFFFFFFFF
if out == target_byte:
flag += chr(char_code)
b = curr_b
found = True
break
if not found:
flag += "?"
print(flag)
if __name__ == "__main__":
solve()
Mission Ghost Signal
翻看data段,找到一个Syclover2025Geek,往回查调用,然后发现
int sub_402DB1()
{
_BYTE v1[32]; // [esp+1Ch] [ebp-20Ch] BYREF
char v2[192]; // [esp+3Ch] [ebp-1ECh] BYREF
char Buffer[256]; // [esp+FCh] [ebp-12Ch] BYREF
_BYTE v4[16]; // [esp+1FCh] [ebp-2Ch] BYREF
int v5; // [esp+20Ch] [ebp-1Ch]
int j; // [esp+210h] [ebp-18h]
char v7; // [esp+217h] [ebp-11h]
int i; // [esp+218h] [ebp-10h]
size_t v9; // [esp+21Ch] [ebp-Ch]
sub_403500();
SetConsoleOutputCP(0xFDE9u);
SetConsoleCP(0xFDE9u);
qmemcpy(v4, "1145141145144332", sizeof(v4));
puts(&::Buffer);
printf(&byte_407090);
if ( fgets(Buffer, 256, (FILE *)iob[0]._ptr) )
{
v9 = strlen(Buffer);
if ( v9 && Buffer[v9 - 1] == 10 )
Buffer[--v9] = 0;
if ( v9 == 25 )
{
sub_401C08(v2, aSyclover2025ge, v4);
memcpy(v1, Buffer, 0x19u);
v5 = 7;
for ( i = 25; i <= 31; ++i )
v1[i] = v5;
sub_402B57(v2, v1, 32);
v7 = 1;
for ( j = 0; j <= 31; ++j )
{
if ( byte_406020[j] != v1[j] )
{
v7 = 0;
break;
}
}
if ( v7 )
puts(&byte_4070F0);
else
puts(&byte_40711C);
return 0;
}
else
{
puts(&byte_4070BC);
return 1;
}
}
else
{
puts(&::Buffer);
return 1;
}
}
其他puts的转字符串是
.rdata:0040707D Buffer db '密码验证系统',0 ; DATA XREF: sub_402DB1+77↑o
.rdata:00407090 ; const char asc_407090
.rdata:00407090 asc_407090 db '请输入压缩包密码: ',0 ; DATA XREF: sub_402DB1+83↑o
.rdata:004070AB ; const char Buffer
.rdata:004070AB Buffer db '输入错误!',0,0 ; DATA XREF: sub_402DB1+B7↑o
.rdata:004070BC ; const char asc_4070BC
.rdata:004070BC asc_4070BC db '特工,你失败了!密码长度不正确。',0,0,0,0
.rdata:004070BC ; DATA XREF: sub_402DB1+10E↑o
.rdata:004070F0 ; const char asc_4070F0
.rdata:004070F0 asc_4070F0 db '恭喜!这是正确的压缩包密码。',0,0,'特工,你失败了!密码不正确。',0,0
就确定了这里是主要加密段了
然后动调patse data
把call 0x402B57(加密)改成call 0x402BE8(解密),然后替换成byte_406020的数据,得出密码
stack_bomb
nop掉了一些push的部分伪c出来了
知道是tea了,然后找出魔改点
from ctypes import c_uint32
def decrypt(v, k):
v0, v1 = c_uint32(v[0]), c_uint32(v[1])
delta = 0x9000000
sum_val = c_uint32(delta * 32)
for _ in range(32):
v1.value -= ((v0.value << 4) + k[2]) ^ (v0.value + sum_val.value) ^ ((v0.value >> 5) + k[3])
v0.value -= ((v1.value << 4) + k[0]) ^ (v1.value + sum_val.value) ^ ((v1.value >> 5) + k[1])
sum_val.value -= delta
return v0.value, v1.value
enc = [
[0x9A8C0C4B, 0xC412FF1C], [0xBFC3A488, 0xB16C8FD0],
[0x4136E319, 0x8835E4FF], [0x118263A7, 0x7C85D629]
]
key = [1, 2, 3, 4]
flag = b''
for g in enc:
d = decrypt(g, key)
flag += d[0].to_bytes(4, 'little') + d[1].to_bytes(4, 'little')
print(flag.decode())
ez_android
打开软件,对应搜索,进入function1
解密
from Crypto.Cipher import DES
import binascii
cipher_text = "43464244374534323530413841423536"
key = "12345678"
def solve_part1():
try:
first_layer = binascii.unhexlify(cipher_text).decode('utf-8')
cipher_bytes = binascii.unhexlify(first_layer)
des = DES.new(key.encode('utf-8'), DES.MODE_ECB)
decrypted = des.decrypt(cipher_bytes)
print(f"Part 1 Flag: {decrypted.decode('utf-8', errors='ignore').strip()}")
except Exception as e:
print(f"Error: {e}")
if __name__ == "__main__":
solve_part1()
function2,进入libwrapper.so层查看,有提示realso,用frida脚本提出来,或者找encrypted_so,所有字节异或0xAA(因为可以出elf文件头),然后发现是rc4,key是mysecret,解出第二部分,第三部分,有一个libfunction3.so,能看到算法,但不知道s盒,要dump出来,最后解密
import struct
IP = [
58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7
]
FP = [
40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25
]
E = [
32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10, 11, 12, 13, 12, 13,
14, 15, 16, 17, 16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25,
24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1
]
P = [
16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25
]
PC1 = [
57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2,
59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, 63, 55, 47, 39,
31, 23, 15, 7, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37,
29, 21, 13, 5, 28, 20, 12, 4
]
PC2 = [
14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 23, 19, 12, 4,
26, 8, 16, 7, 27, 20, 13, 2, 41, 52, 31, 37, 47, 55, 30, 40,
51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
]
SHIFTS = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1]
S_BOX = [
[
[14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7], [0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8], [4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0], [15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13]
],
[
[15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10], [3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5], [0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15], [13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9]
],
[
[10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8], [13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1], [13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7], [1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12]
],
[
[7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15], [13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9], [10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4], [3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14]
],
[
[2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9], [14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6], [4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14], [11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3]
],
[
[12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11], [10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8], [9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6], [4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13]
],
[
[4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1], [13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6], [1, 4, 11, 13, 12, 3, 7, 10, 15, 6, 8, 0, 5, 9, 14, 2], [6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12]
],
[[0] * 16, [0] * 16, [0] * 16, [0] * 16]
]
def c_permute(in_bytes, table, out_bits):
out_len = (out_bits + 7) // 8
out = bytearray(out_len)
for i in range(out_bits):
pos = table[i] - 1
byte_idx = pos // 8
bit_idx = 7 - (pos % 8)
if byte_idx < len(in_bytes):
bit = (in_bytes[byte_idx] >> bit_idx) & 0x01
out[i // 8] |= (bit << (7 - (i % 8)))
return out
def rotl32(val, shift):
shift = shift % 32
return ((val << shift) & 0xFFFFFFFF) | (val >> (32 - shift))
def generate_subkeys(key_bytes):
permuted_key = c_permute(key_bytes, PC1, 56)
c_bytes = permuted_key[0:4]
d_bytes = permuted_key[3:7]
c_int = struct.unpack('>I', c_bytes)[0]
d_int = struct.unpack('>I', d_bytes)[0]
subkeys = []
for s in SHIFTS:
c_int = rotl32(c_int, s)
d_int = rotl32(d_int, s)
c_new = struct.pack('>I', c_int)
d_new = struct.pack('>I', d_int)
combined = bytearray(7)
combined[0:4] = c_new
combined[3:7] = d_new
subkey = c_permute(combined, PC2, 48)
subkeys.append(subkey)
return subkeys
def feistel(R, subkey):
expanded = c_permute(R, E, 48)
for i in range(6):
expanded[i] ^= subkey[i]
output_val = 0
for i in range(8):
idx = i * 6
byte_idx = idx // 8
bit_idx = 7 - (idx % 8)
b0 = (expanded[byte_idx] >> bit_idx) & 0x01
idx5 = idx + 5
byte_idx5 = idx5 // 8
bit_idx5 = 7 - (idx5 % 8)
b5 = (expanded[byte_idx5] >> bit_idx5) & 0x01
row = (b0 << 1) | b5
col = 0
for j in range(1, 5):
idxj = idx + j
byte_idxj = idxj // 8
bit_idxj = 7 - (idxj % 8)
bit = (expanded[byte_idxj] >> bit_idxj) & 0x01
col = (col << 1) | bit
val = S_BOX[i][row][col]
pos_in_int = 28 - (i * 4)
output_val |= (val << pos_in_int)
output_bytes = struct.pack('>I', output_val)
temp = c_permute(output_bytes, P, 32)
R[:] = temp
def des_crypt(key, data, mode='decrypt'):
subkeys = generate_subkeys(key)
if mode == 'decrypt':
subkeys = subkeys[::-1]
block = c_permute(data, IP, 64)
L = block[0:4]
R = block[4:8]
for i in range(16):
temp = bytearray(R)
feistel(R, subkeys[i])
for j in range(4):
R[j] ^= L[j]
L = temp
preoutput = R + L
output = c_permute(preoutput, FP, 64)
return output
def main():
DES_KEY = bytes([0x13, 0x34, 0x57, 0x79, 0x9B, 0xBC, 0xDF, 0xF1])
hex_ciphertext = "AEBCDE9B24029CA7"
ciphertext = bytes.fromhex(hex_ciphertext)
decrypted = des_crypt(DES_KEY, ciphertext, mode='decrypt')
print(f"解密: {decrypted.decode('utf-8').rstrip(chr(0))}")
if __name__ == "__main__":
main()
Th1s_1s_Th3_R3@lly_F1ag!得出





吓哭了
给无机盐大手子orz了
给无机盐神跪了
给无机盐🈸跪了😭
爱你主播