密码学学习记录 2 / 15
- 密码学学习记录|hash md5 算法
- 密码学学习记录|hash md5 算法练习样本一
- 密码学学习记录|hash md5 算法练习样本二
- 密码学学习记录|hash sha1 算法
- 密码学学习记录|hash sha1 算法练习样本一
- 密码学学习记录|hash sha256 算法
- 密码学学习记录|hash sha256 算法练习样本一
- 密码学学习记录|hash sha512 算法
- 密码学学习记录|hash hmac 算法
- 密码学学习记录|des 加解密算法
- 密码学学习记录|des - 3des 算法
- 密码学学习记录|aes 加解密算法
- 密码学学习记录|aes dfa 练习样本一
- 密码学学习记录|aes dfa 练习样本二
- 密码学学习记录|aes dfa 练习样本三
样本来自 Litt1eQ 大佬的公众号 Coder小Q
分析之前可以先使用 unidbg 跑一下,方便动态调试分析
样本逻辑比较简单,只有一个静态的 native 函数,打开 so 即可分析
分析总结:这个样本改的比较彻底,abcd 顺序颠倒,循环左移的位数、K表等
so 分析
分析 sub_990
函数
前面是数据填充,跟常量定义
在往下就是四轮循环,可以看到循环左移的位数也都被改变了
最后就是数据拼接了,核心逻辑就是上面的循环,也就是 transform
函数
python 还原
0x1 定义常量
- 1、md 缓冲器(四个常量)
so
里的常量在这里,循序的可以通过名称来确定,v57
类型是 int64
咱们直接拆成两个就行了,高位在前,低位在后,最后结果就是
A = 0x10325476
B = 0xEFCDAB89
C = 0x67452301
D = 0x98BADCFE
- 2、常数组 T(正弦函数表)
v11
是我们输入的数据 TK
也就是(正弦函数表,我这里改了名字的),一共有 64 个
T = [
0x8A51407D, 0x6A88995D, 0xFD7025F4, 0xA7553036, 0x489E15C1, 0xF5CDB84B, 0xC0FFBCF6, 0x253F7D7E,
0xE93FD535, 0xD6CD6448, 0x01220AE4, 0xD806D023, 0xE84E6EA9, 0x230135D8, 0xC27AE834, 0xF5292BF4,
0x46711AC1, 0xA90A840A, 0xFD1BBEF0, 0x687810E5, 0x8C37FC1B, 0xFFFD6EC6, 0x8867BEAC, 0x6C96FED4,
0xFDBF77AC, 0xA59C8134, 0x4AC99BE5, 0xF66D568A, 0xBF80B2C1, 0x277D05E4, 0xEA2C8E1F, 0xD58FA982,
0x03661ADB, 0xD93BE6CA, 0xE7585F52, 0x20C23A76, 0xC3F22CE1, 0xF47FB4D2, 0x4442B612, 0xAABC73EB,
0xFCC24453, 0x66657006, 0x8E1BE7C3, 0xFFF5BB27, 0x867B8079, 0x6EA336BB, 0xFE09B282, 0xA3E07FDA,
0x4CF3A208, 0xF708037E, 0xBDFDD143, 0x29B9C389, 0xEB1494A7, 0xD44DA632, 0x05AA195E, 0xDA6CA20A,
0xE65DAC20, 0x1E8296E0, 0xC5658374, 0xF3D1564B, 0x4212F2E5, 0xAC6AF723, 0xFC63B7E7, 0x6450C165
]
- 3、循环左移位数(我这里称之为 S)
s1 = [25, 20, 15, 10] * 4
s2 = [27, 23, 18, 12] * 4
s3 = [28, 21, 16, 9] * 4
s4 = [26, 22, 17, 11] * 4
S = s1 + s2 + s3 + s4
0x2 数据填充
- 这个是标准的
0x3 四轮循环
- 这个需要先确定 abcd 循序
a = FF(a, b, c, d, M[0], S[0], T[0])
d = FF(d, a, b, c, M[1], S[1], T[1])
c = FF(c, d, a, b, M[2], S[2], T[2])
b = FF(b, c, d, a, M[3], S[3], T[3])
这是标准的代码(博主测试过,这个样本不是标准的),那要咋确定呢,其实也简单
改了名称之后,整体逻辑都比较清晰了,所以直接 copy so
循序即可
c = b + ROR4(c + ((a & d) | (b & ~a)) + M[0] + T[0], S[0])
a = c + ROR4(a + ((b & d) | (c & ~d)) + M[1] + T[1], S[1])
d = a + ROR4(d + ((c & b) | (a & ~b)) + M[2] + T[2], S[2])
b = d + ROR4(b + ((a & c) | (d & ~c)) + M[3] + T[3], S[3])
最终循序也就是这样的
unidbg
- 可以使用 unidbg 动态调试,或者 hook 验证代码逻辑是否正确,博主提供一段 hook 代码,大家自行体会
public void inlineHook() {
// 第一轮 hook
emulator.getBackend().hook_add_new(new CodeHook() {
@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == (module.base + 0xA66)) {
Arm32RegisterContext ctx = emulator.getContext();
System.out.println("第一轮循环 md5C R3 25: 0x" + Long.toHexString(ctx.getR3Long()));
}
}
@Override
public void onAttach(UnHook unHook) {
}
@Override
public void detach() {
}
}, module.base + 0xA66, module.base + 0xA66, null);
emulator.getBackend().hook_add_new(new CodeHook() {
@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == (module.base + 0xA7A)) {
Arm32RegisterContext ctx = emulator.getContext();
System.out.println("第一轮循环 md5A R2 20: 0x" + Long.toHexString(ctx.getR2Long()));
}
}
@Override
public void onAttach(UnHook unHook) {
}
@Override
public void detach() {
}
}, module.base + 0xA7A, module.base + 0xA7A, null);
emulator.getBackend().hook_add_new(new CodeHook() {
@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == (module.base + 0xA90)) {
Arm32RegisterContext ctx = emulator.getContext();
System.out.println("第一轮循环 md5D R1 15: 0x" + Long.toHexString(ctx.getR1Long()));
}
}
@Override
public void onAttach(UnHook unHook) {
}
@Override
public void detach() {
}
}, module.base + 0xA90, module.base + 0xA90, null);
emulator.getBackend().hook_add_new(new CodeHook() {
@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == (module.base + 0xAAC)) {
Arm32RegisterContext ctx = emulator.getContext();
System.out.println("第一轮循环 md5B R0 10: 0x" + Long.toHexString(ctx.getR0Long()));
}
}
@Override
public void onAttach(UnHook unHook) {
}
@Override
public void detach() {
}
}, module.base + 0xAAC, module.base + 0xAAC, null);
// 第二轮 hook
emulator.getBackend().hook_add_new(new CodeHook() {
@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == (module.base + 0xAFA)) {
Arm32RegisterContext ctx = emulator.getContext();
System.out.println("第二轮循环 md5C R3 27: 0x" + Long.toHexString(ctx.getR3Long()));
}
}
@Override
public void onAttach(UnHook unHook) {
}
@Override
public void detach() {
}
}, module.base + 0xAFA, module.base + 0xAFA, null);
emulator.getBackend().hook_add_new(new CodeHook() {
@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == (module.base + 0xB1A)) {
Arm32RegisterContext ctx = emulator.getContext();
System.out.println("第二轮循环 md5A R2 23: 0x" + Long.toHexString(ctx.getR2Long()));
}
}
@Override
public void onAttach(UnHook unHook) {
}
@Override
public void detach() {
}
}, module.base + 0xB1A, module.base + 0xB1A, null);
emulator.getBackend().hook_add_new(new CodeHook() {
@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == (module.base + 0xB3A)) {
Arm32RegisterContext ctx = emulator.getContext();
System.out.println("第二轮循环 md5D R1 18: 0x" + Long.toHexString(ctx.getR1Long()));
}
}
@Override
public void onAttach(UnHook unHook) {
}
@Override
public void detach() {
}
}, module.base + 0xB3A, module.base + 0xB3A, null);
emulator.getBackend().hook_add_new(new CodeHook() {
@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == (module.base + 0xB5A)) {
Arm32RegisterContext ctx = emulator.getContext();
System.out.println("第二轮循环 md5B R0 12: 0x" + Long.toHexString(ctx.getR0Long()));
}
}
@Override
public void onAttach(UnHook unHook) {
}
@Override
public void detach() {
}
}, module.base + 0xB5A, module.base + 0xB5A, null);
// 第三轮 hook
emulator.getBackend().hook_add_new(new CodeHook() {
@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == (module.base + 0xBAE)) {
Arm32RegisterContext ctx = emulator.getContext();
System.out.println("第三轮循环 md5C R3 28: 0x" + Long.toHexString(ctx.getR3Long()));
}
}
@Override
public void onAttach(UnHook unHook) {
}
@Override
public void detach() {
}
}, module.base + 0xBAE, module.base + 0xBAE, null);
emulator.getBackend().hook_add_new(new CodeHook() {
@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == (module.base + 0xBCE)) {
Arm32RegisterContext ctx = emulator.getContext();
System.out.println("第三轮循环 md5A R2 21: 0x" + Long.toHexString(ctx.getR2Long()));
}
}
@Override
public void onAttach(UnHook unHook) {
}
@Override
public void detach() {
}
}, module.base + 0xBCE, module.base + 0xBCE, null);
emulator.getBackend().hook_add_new(new CodeHook() {
@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == (module.base + 0xBEA)) {
Arm32RegisterContext ctx = emulator.getContext();
System.out.println("第三轮循环 md5D R1 16: 0x" + Long.toHexString(ctx.getR1Long()));
}
}
@Override
public void onAttach(UnHook unHook) {
}
@Override
public void detach() {
}
}, module.base + 0xBEA, module.base + 0xBEA, null);
emulator.getBackend().hook_add_new(new CodeHook() {
@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == (module.base + 0xBF6)) {
Arm32RegisterContext ctx = emulator.getContext();
System.out.println("第三轮循环 md5B R0 9: 0x" + Long.toHexString(ctx.getR0Long()));
}
}
@Override
public void onAttach(UnHook unHook) {
}
@Override
public void detach() {
}
}, module.base + 0xBF6, module.base + 0xBF6, null);
// 第四轮 hook
emulator.getBackend().hook_add_new(new CodeHook() {
@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == (module.base + 0xC40)) {
Arm32RegisterContext ctx = emulator.getContext();
System.out.println("第四轮循环 md5C R3 26: 0x" + Long.toHexString(ctx.getR3Long()));
}
}
@Override
public void onAttach(UnHook unHook) {
}
@Override
public void detach() {
}
}, module.base + 0xC40, module.base + 0xC40, null);
emulator.getBackend().hook_add_new(new CodeHook() {
@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == (module.base + 0xC58)) {
Arm32RegisterContext ctx = emulator.getContext();
System.out.println("第四轮循环 md5A R2 22: 0x" + Long.toHexString(ctx.getR2Long()));
}
}
@Override
public void onAttach(UnHook unHook) {
}
@Override
public void detach() {
}
}, module.base + 0xC58, module.base + 0xC58, null);
emulator.getBackend().hook_add_new(new CodeHook() {
@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == (module.base + 0xC76)) {
Arm32RegisterContext ctx = emulator.getContext();
System.out.println("第四轮循环 md5D R1 17: 0x" + Long.toHexString(ctx.getR1Long()));
}
}
@Override
public void onAttach(UnHook unHook) {
}
@Override
public void detach() {
}
}, module.base + 0xC76, module.base + 0xC76, null);
emulator.getBackend().hook_add_new(new CodeHook() {
@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == (module.base + 0xC8E)) {
Arm32RegisterContext ctx = emulator.getContext();
System.out.println("第四轮循环 md5B R0 11: 0x" + Long.toHexString(ctx.getR0Long()));
}
}
@Override
public void onAttach(UnHook unHook) {
}
@Override
public void detach() {
}
}, module.base + 0xC8E, module.base + 0xC8E, null);
}
最后
unidbg
输入 1638845144244
结果 F7CE6906C0E04E6CEE43DD38575D1D9F
使用 python
输入输出也都是相同的