hook me(reverse)


frida脚本

发现是单字节相关的异或

随便输入一些

Java.perform(function() {
var main = Java.use("com.example.hookme.MainActivity");
main.rc4Encrypt.implementation=function (args){
console.log(args);
console.log("----------");
var re=this.rc4Encrypt(args);
console.log("result",re);
}

});

先找密文

Java.perform(function() {
var main = Java.use("com.example.hookme.MainActivity");
main.hexStringToByteArray.implementation=function (args){
console.log(args);
console.log("----------");
var re=this.hexStringToByteArray(args);
console.log("result",re);
}

});

这里随便改输入,发现这里hook到的密文都是一样的,证明密文跟输入无关

这里发现输入都是单字节相关的,证明它应该就是普通的rc4,那可以直接通过异或拿到密钥,这里hook到的密文可以看出输入是38字节的

输入38字节a

得到相应密文,之后直接异或得到密钥,然后再异或密文就可以得到明文了

a = "a" * 38
xor = [ -11, 56, -72, -114, -87, -16, -28, -45, -8, 20, -74, -75,
-56, -108, -20, 50, -46, -87, -91, -29, -27, 14, 28, -76,
-94, -71, 126, -109, -42, -23, -54, 117, -3, -120, -58,
-49, -87, 1 ]
an = []
for i in range(len(xor)):
v = ord(a[i]) ^ (xor[i] & 0xFF)
an.append(v & 0xFF)
aaa = [ -14, 53, -72, -120, -77, -12, -32, -117, -1, 23, -25, -30,
-101, -61, -65, 103, -48, -7, -95, -73, -74, 88, 27, -76,
-95, -21, 41, -106, -124, -23, -103, 35, -88, -47, -109,
-54, -7, 29 ]
aaaaa = []
for i in range(len(aaa)):
w = aaa[i] ^ an[i]
aaaaa.append(w & 0xFF)

result = bytes(aaaaa)
print(result)

简单编码(密码学)

猜测A是1,B是零,猜测是二进制,因为这个只有两个字母

def decode_morse_ab(input_str):
# 预处理
groups = input_str.strip().split()

result = ''
for group in groups:
# 将 A 映射为 0,B 映射为 1
binary = group.replace('A', '1').replace('B', '0')
try:
char_code = int(binary, 2)
result += chr(char_code)
except:
result += '?'

return result


# 粘贴你的 AB 编码数据
data = '''
ABBAABB ABBABAB ABABAAA ABABAAB ABBBBAA ABBAABA ABABBAA ABBAAAA ABBAAAB ABBABAB ABBBAAA ABAABBB ABABBAA ABABABB ABABBAA ABBABBB ABBABAA ABABABA ABAABAB ABBBAAA ABBBABA ABABBAB ABBBBAA ABABBAB ABBBAAA ABBABAB ABBAABA ABABAAA ABABABA AABBAB ABBBABB ABBAABA ABBABAB AABABA ABBBBAA ABBBAAB ABBAABA AABBAB ABABBAA ABBAAAB ABBBAAA ABBABAB ABBABAA ABABABB ABBBABA ABABABB ABBAABB ABBABAA ABBABAB ABBABAB ABABAAA ABBBABA AABABB ABABBAB AABBAB ABABAAA ABBAAAB ABBBBAB ABBBAAA ABABABA ABBAAAA ABABAAB ABABABB ABBABBA ABBABAB AABABA ABBABAA ABBBABA ABBBABA AABBAA ABBBBAA ABBAAAA ABABBBB ABBABAB ABABABB ABAABBB ABBAAAA ABABAAA ABABABB ABBABAA ABBABBA ABABABA ABAABAB ABABABA AABABB ABABBAB ABBBBAA ABBBBAB ABBBAAA ABABAAB ABBABBB ABABAAB ABBAAAA ABAABAB ABBBABB ABBABAA ABBABAB ABABABA ABAABAB ABBBABA ABBAABA AABBAB ABABBAA ABAABAB ABBBAAA ABBABAB ABBBABA ABAABBB ABABBBA ABABABB ABABBAA ABBABBB ABBABAA ABAABAB ABABABA ABBBAAB ABABBAA ABBAABA ABABBAA ABAABAB ABBBAAA ABBABAB ABBABBB ABBBABB ABBBABA ABABBAA ABBABAB ABABABA ABBAABA ABAABAB ABBAABA ABBABBB ABBBAAA ABBAABA ABBBBAA ABBAAAA ABBABAA ABABBAB ABBABAA ABAABBB ABABABA ABABABB ABABABB AABBAB ABBAAAB ABBBBAB ABABABA ABBBABA AABBAB ABABABA ABBABAB ABBBAAB ABBBAAA ABBAAAB ABBBBAA ABBBBAA ABBABAA ABBAABA AABBAB ABBBABA
'''

# 输出解码结果
decoded = decode_morse_ab(data)
print("解码结果:")
print(decoded)

得到的结果是base32编码后的

import base64

data = "LJWVCMSONJGXSTSHKUZGERCRGJMWU2DMJ5CFM2SNGJKTETLKJJWE4R2WNBGUOVTIJ5KEE3COPJTXOWTKIUZU4RCBGVHVOZDKJUZEM2SZGJEXQTSHKZUFSMSZGJHDESJUMZMHGMCOKRKXUTT2NBUE2UJFGNCCKM2E"

# Base32 解码
decoded_bytes = base64.b32decode(data)
print("Base32 解码结果为:")
print(decoded_bytes)

# 如果内容是字符串(如 flag),可以再尝试 decode 为 utf-8
try:
print("\n转为字符串:")
print(decoded_bytes.decode('utf-8'))
except UnicodeDecodeError:
print("\n无法转换为 UTF-8 字符串,可能是非文本内容或有混淆。")

有%3D,然后URL解码

import urllib.parse

url_encoded = "ZmQ2NjMyNGU2bDQ2YjhlODVjM2U2MjJlNGVhMGVhOTBlNzgwZjE3NDA5OWdjM2FjY2IxNGVhY2Y2N2I4fXs0NTUzNzhhMQ%3D%3D"
decoded_url = urllib.parse.unquote(url_encoded)
print("URL 解码后:")
print(decoded_url)

得到的经典就是base64

感觉排序出了问题,感觉是栅栏编码,

def rail_fence_decrypt(cipher, rails):
# Rail Fence 解密
pattern = list(range(rails)) + list(range(rails - 2, 0, -1))
len_pattern = len(pattern)
index_count = [0] * rails
for i in range(len(cipher)):
index_count[pattern[i % len_pattern]] += 1

idx = 0
fence = [[] for _ in range(rails)]
for r in range(rails):
for _ in range(index_count[r]):
fence[r].append(cipher[idx])
idx += 1

result = ''
pos = [0] * rails
for i in range(len(cipher)):
r = pattern[i % len_pattern]
result += fence[r][pos[r]]
pos[r] += 1

return result

def fix_garbled(hexstr):
return hexstr.replace('g', '9').replace('l', '1')

cipher = "fd66324e6l46b8e85c3e622e4ea0ea90e780f174099gc3accb14eacf67b8}{455378a1"

for rail in range(2, 10):
plain = rail_fence_decrypt(cipher, rail)
if 'flag{' in plain or '{' in plain and '}' in plain:
print(f"\n✅ 栏数: {rail}")
print("解密结果:", plain)

start = plain.find('{')
end = plain.find('}', start)
if start != -1 and end != -1:
content = plain[start+1:end]
fixed = fix_garbled(content)
print("💡 猜测 flag: flag{" + fixed + "}")

dp(密码学)

dp泄露

直接通过私钥的dp恢复整个私钥,枚举所有可能的k,还原p

import gmpy2 as gp

n = 110231451148882079381796143358970452100202953702391108796134950841737642949460527878714265898036116331356438846901198470479054762675790266666921561175879745335346704648242558094026330525194100460497557690574823790674495407503937159099381516207615786485815588440939371996099127648410831094531405905724333332751
dp = 3086447084488829312768217706085402222803155373133262724515307236287352098952292947424429554074367555883852997440538764377662477589192987750154075762783925
c = 59325046548488308883386075244531371583402390744927996480498220618691766045737849650329706821216622090853171635701444247741920578127703036446381752396125610456124290112692914728856924559989383692987222821742728733347723840032917282464481629726528696226995176072605314263644914703785378425284460609365608120126
e = 65537

for i in range(1, e):
if (dp * e - 1) % i == 0:
p = ((dp * e - 1) // i) + 1
if n % p == 0:
q = n // p
phi = (p - 1) * (q - 1)
d = gp.invert(e, phi)
m = pow(c, d, n)
print(m)
print("------------")
print(hex(m)[2:])
print("------------")
print(bytes.fromhex(hex(m)[2:]))
break

easy_rsa(密码学)

分解大质数后计算欧拉函数之后算出私钥解密就行

import gmpy2

# 已知参数
e = 65537
n = 1000000000000000000000000000156000000000000000000000000005643
c = 418535905348643941073541505434424306523376401168593325605206

# Step 1: 使用 Fermat 分解法求 p, q
a = gmpy2.isqrt(n)
if a * a < n:
a += 1

b2 = a * a - n
while not gmpy2.is_square(b2):
a += 1
b2 = a * a - n

b = gmpy2.isqrt(b2)
p = a - b
q = a + b

print(f"[+] p = {p}")
print(f"[+] q = {q}")

# Step 2: 计算 φ(n)
phi = (p - 1) * (q - 1)

# Step 3: 计算 d = e^-1 mod φ(n)
d = gmpy2.invert(e, phi)

# Step 4: 解密 m = c^d mod n
m = pow(c, d, n)

# Step 5: 输出结果
print("------------")
print(f"[+] m (十进制) = {m}")
hex_m = hex(m)[2:]
if len(hex_m) % 2 != 0:
hex_m = "0" + hex_m
print(f"[+] m (hex) = {hex_m}")
print("------------")
try:
print(f"[+] 明文:{bytes.fromhex(hex_m).decode()}")
except:
print("[!] 明文无法直接解码成 UTF-8 字符串,可尝试手动分析 hex。")

Terminal Hacker(misc)

按照步骤输入得到flag

你知道Base么(reverse)

先获得key,tea解密

#include <stdio.h>
#include <stdint.h>

//加密函数
void encrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0, i;
uint32_t delta = 0x9e3779b9;
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
for (i = 0; i < 32; i++) {
sum += delta;
v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
}
v[0] = v0; v[1] = v1;
}

//解密函数
void decrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0xC6EF3720, i;
uint32_t delta = 0x9e3779b9;
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
for (i = 0; i < 32; i++) {
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
sum -= delta;
}
v[0] = v0; v[1] = v1;
}

int main()
{
// v为要加解密的数据,两个32位无符号整数
uint32_t v[2] = { 0xA92F3865, 0x9E60E953 };
// k为加解密密钥,4个32位无符号整数,密钥长度为128位
uint32_t k[4] = { 0x12345678,0x3456789A,0x89ABCDEF,0x12345678 };
int n = sizeof(v) / sizeof(uint32_t);
decrypt(v, k);
printf("解密后的数据:0x%x 0x%x\n", v[0], v[1]);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < sizeof(uint32_t) / sizeof(uint8_t); j++)
{
printf("%c", (v[i] >> (j * 8)) & 0xFF);
}
}
printf("\n");
return 0;
}
//y0uokTea

再rc4解密获得base32的表,密钥就是前一个的输入

这里虽然分开了但根据长度应该是一起的

#include<stdio.h>

/*
RC4初始化函数
*/
void rc4_init(unsigned char* s, unsigned char* key, unsigned long Len_k)
{
int i = 0, j = 0;
char k[256] = { 0 };
unsigned char tmp = 0;
for (i = 0; i < 256; i++) {
s[i] = i;
k[i] = key[i % Len_k];
}
for (i = 0; i < 256; i++) {
j = (j + s[i] + k[i]) % 256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
}

/*
RC4加解密函数
unsigned char* Data 加解密的数据
unsigned long Len_D 加解密数据的长度
unsigned char* key 密钥
unsigned long Len_k 密钥长度
*/
void rc4_crypt(unsigned char* Data, unsigned long Len_D, unsigned char* key, unsigned long Len_k) //加解密
{
unsigned char s[256];
rc4_init(s, key, Len_k);
int i = 0, j = 0, t = 0;
unsigned long k = 0;
unsigned char tmp;
for (k = 0; k < Len_D; k++) {
i = (i + 1) % 256;
j = (j + s[i]) % 256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
t = (s[i] + s[j]) % 256;
Data[k] = Data[k] - s[t];
}
}
void main()
{
//字符串密钥
unsigned char key[] = "y0uokTea";
unsigned long key_len = sizeof(key) - 1;
//数组密钥
//unsigned char key[] = {};
//unsigned long key_len = sizeof(key);

//加解密数据
unsigned char data[64] = {0};
data[0] = -44;
data[1] = 89;
data[2] = 35;
data[3] = 118;
data[4] = -76;
data[5] = -65;
data[6] = -29;
data[7] = 44;
data[8] = 88;
data[9] = -113;
data[10] = 86;
data[11] = 25;
data[12] = -38;
data[13] = -16;
data[14] = -64;
data[15] = -67;
data[16] = 54;
data[17] = 61;
data[18] = 123;
data[19] = 70;
data[20] = 27;
data[21] = -72;
data[22] = 23;
data[23] = 31;
data[24] = -29;
data[25] = -48;
data[26] = 3;
data[27] = 69;
data[28] = -51;
data[29] = 4;
data[30] = -19;
data[31] = -55;
data[32] = 103;
data[33] = -26;
data[34] = -85;
data[35] = 41;
data[36] = -89;
data[37] = -68;
data[38] = 11;
data[39] = -34;
data[40] = 92;
data[41] = 48;
data[42] = 113;
data[43] = -41;
data[44] = -43;
data[45] = 90;
data[46] = -58;
data[47] = -97;
data[48] = 64;
data[49] = 101;
data[50] = -60;
data[51] = 113;
data[52] = -87;
data[53] = -61;
data[54] = -82;
data[55] = -39;
data[56] = -75;
data[57] = -27;
data[58] = 18;
data[59] = -116;
data[60] = 0x80;
data[61]='R';
data[62] = '4';
data[63] = '6';
//加解密
rc4_crypt(data, 64, key, key_len);

for (int i = 0; i < sizeof(data); i++)
{
printf("%c", data[i]);
}
printf("\n");
return;
}
//gVxwoFhPyT/YM0BKcHe4b8GCUZtlnLW2SJO51IErk+q6vzpamdARX9siND3uQfj7

自定义的base32编码,直接通过得到的表和密文解密就可以了

def decode_custom_base32(encoded_str):
# 自定义字符表(从原始代码中提取)
a3_table = "gVxwoFhPyT/YM0BKcHe4b8GCUZtlnLW2SJO51IErk+q6vzpamdARX9siND3uQfj7"

# 构建字符到5-bit值的映射(考虑+1偏移)
char_map = {}
for value in range(32):
char = a3_table[value + 1] # 编码时使用的字符位置
char_map[char] = value

# 去除可能存在的填充字符(根据实际编码情况调整)
encoded_str = encoded_str.strip('=')

# 计算输出缓冲区长度
decoded_len = (len(encoded_str) * 5) // 8
decoded = bytearray(decoded_len)

buffer = 0
buffer_bits = 0
idx = 0

for char in encoded_str:
# 查找字符对应的5-bit值(若重复则取第一个)
if char not in char_map:
raise ValueError(f"无效字符: {char}")
value = char_map[char]

buffer = (buffer << 5) | value
buffer_bits += 5

if buffer_bits >= 8:
buffer_bits -= 8
decoded[idx] = (buffer >> buffer_bits) & 0xFF
idx += 1
buffer &= (1 << buffer_bits) - 1 # 清除已处理的高位

return bytes(decoded)


# ===================== 使用示例 =====================
if __name__ == "__main__":
# 编码后的字符串(替换为你的实际数据)
encoded_data = "0tCPwtnncFZyYUlSK/4Cw0/echcG2lteBWnG2Ulw0htCYTMW"

# 执行解码
try:
decoded_data = decode_custom_base32(encoded_data)
print("[+] 解码成功!")
print("原始数据(HEX):", decoded_data.hex())
print("尝试解析为字符串:", decoded_data.decode('utf-8', errors='replace'))
except Exception as e:
print("[-] 解码失败:", e)

ezBase(reverse)

用ida打开之后,显示的函数很少
用Exeinfo打开

有UPX壳

用010打开看一下
UPX被改成了upx
修改回来,再进行脱壳

密文加密之后应该是等于
iP}ui7siC`otMgAh5o]Tg<4jPmtIvM5CI4h644K7M~KVg=
sub_140001130应该就是加密函数
双击进去看看

应该是Base64加密
而且编码被改变了

AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789+/

最后的时候进行了异或(异或4)
那么解密的时候先异或再base64解密

mTyqm3wmGdkpIcEzl1kYPc80nTipMrI1GzM0l200O3IzORc9