上海省赛PY很严重……整体体验感很差。虽然说还是没能进前25,好在也不是一无所获:逆向AK了,算是初步了解了32位运行64位代码的模式和特征。
Hell’s Gate
32位exe
表面看上去是个RC4
然而钩子挂在了0x00416DFF
上
交叉引用定位到0x00416F90
,这里有个反调试NtQueryInformationProcess
,patch掉之后
进入sub_4174C0
后,会发现调用了一堆函数,这里就拿sub_4171B0
分析
会发现没法反编译,因为它是32位程序调用64位代码,具体可参考文章
知道他是64位代码之后,采用静态分析
修改PE64后,IDA64打开,Rebase Segment之后,再手动转换函数
看到形如
void __fastcall __noreturn sub_171BF(int a1, int a2) { void *retaddr[2]; // [rsp+8h] [rbp+0h] LODWORD(retaddr[1]) = a1; dword_20400[a1] = a2; JUMPOUT(0x23000893A9i64); }
分析传参顺序和操作,会发现其实是基于栈的操作
// author: Mas0n // Time: 2021/10/31 // Desc: It's all about getting better. #include <stdio.h> #include <stdint.h> #include <windows.h> #include <string.h> int main() { DWORD dword_20400[768] = {0}; char input_4203E0[96] = {"1111111111111111111111111111111"}; dword_20400[0] = 0x12345678; dword_20400[1] = 0x87654321; dword_20400[2] = 0x13243546; dword_20400[3] = 0x64534231; *((DWORD*)(input_4203E0 + 32)) = dword_20400[0]; *((DWORD*)(input_4203E0 + 40)) = dword_20400[1]; *((DWORD*)(input_4203E0 + 48)) = dword_20400[2]; *((DWORD*)(input_4203E0 + 56)) = dword_20400[3]; dword_20400[0] = 0xB879379E; *((DWORD*)(input_4203E0 + 64)) = dword_20400[0]; for (int j = 0; j < 32; j += 8) { dword_20400[0] = *((DWORD*)(input_4203E0 + j)); dword_20400[1] = *((DWORD*)(input_4203E0 + j + 4)); *((DWORD*)(input_4203E0 + 72)) = dword_20400[0]; *((DWORD*)(input_4203E0 + 80)) = dword_20400[1]; dword_20400[0] = 0x00000000; *((DWORD*)(input_4203E0 + 88)) = dword_20400[0]; for (int k = 0; k < 16; ++k) { dword_20400[0] = *((DWORD*)(input_4203E0 + 88)); dword_20400[1] = *((DWORD*)(input_4203E0 + 64)); dword_20400[0] += dword_20400[1]; *((DWORD*)(input_4203E0 + 88)) = dword_20400[0]; dword_20400[0] = *((DWORD*)(input_4203E0 + 80)); dword_20400[0] <<= 4; dword_20400[1] = *((DWORD*)(input_4203E0 + 32)); dword_20400[0] += dword_20400[1]; dword_20400[1] = *((DWORD*)(input_4203E0 + 80)); dword_20400[2] = *((DWORD*)(input_4203E0 + 88)); dword_20400[1] += dword_20400[2]; dword_20400[2] = *((DWORD*)(input_4203E0 + 80)); dword_20400[2] >>= 5; dword_20400[3] = *((DWORD*)(input_4203E0 + 40)); dword_20400[2] += dword_20400[3]; dword_20400[1] ^= dword_20400[2]; dword_20400[0] ^= dword_20400[1]; dword_20400[1] = *((DWORD*)(input_4203E0 + 72)); dword_20400[1] += dword_20400[0]; *((DWORD*)(input_4203E0 + 72)) = dword_20400[1]; dword_20400[0] = *((DWORD*)(input_4203E0 + 72)); dword_20400[0] <<= 4; dword_20400[1] = *((DWORD*)(input_4203E0 + 48)); dword_20400[0] += dword_20400[1]; dword_20400[1] = *((DWORD*)(input_4203E0 + 72)); dword_20400[2] = *((DWORD*)(input_4203E0 + 88)); dword_20400[1] += dword_20400[2]; dword_20400[2] = *((DWORD*)(input_4203E0 + 72)); dword_20400[2] >>= 5; dword_20400[3] = *((DWORD*)(input_4203E0 + 56)); dword_20400[2] += dword_20400[3]; dword_20400[1] ^= dword_20400[2]; dword_20400[0] ^= dword_20400[1]; dword_20400[1] = *((DWORD*)(input_4203E0 + 80)); dword_20400[1] += dword_20400[0]; *((DWORD*)(input_4203E0 + 80)) = dword_20400[1]; } dword_20400[0] = *((DWORD*)(input_4203E0 + 72)); dword_20400[1] = *((DWORD*)(input_4203E0 + 80)); *((DWORD*)(input_4203E0 + j)) = dword_20400[0]; *((DWORD*)(input_4203E0 + j + 4)) = dword_20400[1]; } for (int i = 0; i < 32; i += 1) { printf("%x", input_4203E0[i]); } return 0; }
抄下来,GCC重编译,放进IDA,呈现如下
strcpy(v10, "1111111111111111111111111111111"); v11 = 0x12345678i64; v12 = 0x87654321i64; v13 = 0x13243546i64; v14 = 0x64534231i64; v15 = 0xB879379Ei64; v16 = 0i64; v17 = 0i64; v18 = 0i64; v3 = (__int64 *)v10; v4 = v10; do { v5 = *(_DWORD *)v4; v6 = *((_DWORD *)v4 + 1); v7 = v15; v8 = 16; do { v5 += (v12 + (v6 >> 5)) ^ (v6 + v7) ^ (v11 + 16 * v6); v6 += (v5 + v7) ^ (v14 + (v5 >> 5)) ^ (v13 + 16 * v5); v7 += v15; --v8; } while ( v8 ); LODWORD(v18) = 16 * v15; LODWORD(v17) = v6; LODWORD(v16) = v5; *(_DWORD *)v4 = v5; *((_DWORD *)v4 + 1) = v6; v4 += 8; } while ( v4 != (char *)&v11 ); do { printf("%x", (unsigned int)*(char *)v3); v3 = (__int64 *)((char *)v3 + 1); } while ( v3 != &v11 );
显然tea,撸脚本解
// author: Mas0n // Time: 2021/10/31 // Desc: It's all about getting better. #include <stdio.h> #include <stdint.h> #include <windows.h> #include <string.h> void decrypt (DWORD* v) { unsigned int v4; // ecx unsigned int v5; // edx int v6; // er8 DWORD key0; // [rsp+40h] [rbp-68h] BYREF DWORD key1; // [rsp+48h] [rbp-60h] DWORD key2; // [rsp+50h] [rbp-58h] DWORD key3; // [rsp+58h] [rbp-50h] key0 = 0x12345678; key1 = 0x87654321; key2 = 0x13243546; key3 = 0x64534231; int round = 0; DWORD sum = 0; while (round < 4) { sum = 0; for (int i = 0; i < 16; ++i) { sum += 0xB879379E; } v6 = 16; v4 = v[round*2]; v5 = v[round*2+1]; do { v5 -= (v4 + sum) ^ (key3 + (v4 >> 5)) ^ (key2 + 16 * v4); v4 -= (v5 + sum) ^ (key1 + (v5 >> 5)) ^ (key0 + 16 * v5); sum -= 0xB879379E; --v6; } while ( v6 ); v[round*2] = v4; v[round*2+1] = v5; round += 1; } } int main() { DWORD unk_41F8B0[8] = { 0x2C94650B, 0x78494E9E, 0xE7FACF44, 0x48F9DBFB, 0x547BB145, 0x925D2542, 0x69A9F4C4, 0x9A96A1D8 }; decrypt(unk_41F8B0); for (int i = 0; i < 8; ++i) { printf("0x%lx, ", unk_41F8B0[i]); } printf("\n"); return 0; }
hello
Android逆向,Java层需要关注的函数new hi().getSignatures(view)
if (MainActivity.this.input.getText().length() == 42) { Toast makeText = Toast.makeText(MainActivity.this, MainActivity.this.stringFromJNI(MainActivity.this.input.getText().toString(), new hi().getSignatures(view)), 1); makeText.setGravity(0, 0, -700); makeText.show(); return; }
adb install -t hello.apk
,logcat直接白给
public String getSignatures(View view) throws PackageManager.NameNotFoundException, NoSuchAlgorithmException { MessageDigest.getInstance("MD5"); Signature[] signatureArr = view.getContext().getPackageManager().getPackageInfo(BuildConfig.APPLICATION_ID, 64).signatures; if (signatureArr.length <= 0) { return "this_is_your_gift!"; } Signature signature = signatureArr[0]; Log log = this.Log; Log.i("hello", signature.toCharsString()); // logcat return signature.toCharsString(); }
ndk定位函数导出函数Java_com_example_hello_MainActivity_stringFromJNI
做了2种变换
第一部分简单的用得到的hash异或
arr = (*a1)->GetStringUTFChars(a1, input, 0LL); hash = (*a1)->GetStringUTFChars(a1, a4, 0LL); if ( *arr ) { hash2 = hash; *arr ^= hash[327]; if ( strlen(arr) >= 2uLL ) { v9 = 1LL; v10 = 354; do { arr[v9] ^= hash2[v10] + v9; ++v9; v10 += 27; } while ( strlen(arr) > v9 ); } }
第二部分简单的位运算
v11 = (arr[32] >> 3) & 0xFFFFE01F | (0x20 * arr[32]); v12 = (arr[33] >> 3) & 0x1F | (0x20 * arr[33]); v13 = (arr[35] >> 3) & 0xFFFFE01F | (32 * arr[35]); v14 = (arr[36] >> 3) & 0xFFFFE01F | (32 * arr[36]); v15 = (arr[37] >> 3) & 0xFFFFE01F | (32 * arr[37]); v16 = (arr[38] >> 3) & 0xFFFFE01F | (32 * arr[38]); v17 = (arr[39] >> 3) & 0xFFFFE01F | (32 * arr[39]); v18 = vorrq_s8(vshrq_n_u8(*arr, 3uLL), vshlq_n_s8(*arr, 5uLL)); v19 = (arr[40] >> 3) & 0xFFFFE01F | (32 * arr[40]); v20 = vorrq_s8(vshrq_n_u8(*(arr + 1), 3uLL), vshlq_n_s8(*(arr + 1), 5uLL)); v21 = (arr[41] >> 3) & 0xFFFFE01F | (32 * arr[41]); arr[34] = (arr[34] >> 3) & 0x1F | (32 * arr[34]); arr[32] = v11; arr[33] = v12; arr[35] = v13; arr[36] = v14; arr[37] = v15; arr[38] = v16; arr[39] = v17; arr[40] = v19; arr[41] = v21;
上脚本
# -*- coding:utf-8 -*- """ @Author: Mas0n @File: dhb.py @Time: 2021-10-31 11:54 @Desc: It's all about getting better. """ arr = [0xCA, 0xEB, 0x4A, 0x8A, 0x68, 0xE1, 0xA1, 0xEB, 0xE1, 0xEE, 0x6B, 0x84, 0xA2, 0x6D, 0x49, 0xC8, 0x8E, 0x0E, 0xCC, 0xE9, 0x45, 0xCF, 0x23, 0xCC, 0xC5, 0x4C, 0x0C, 0x85, 0xCF, 0xA9, 0x8C, 0xF6, 0xE6, 0xD6, 0x26, 0x6D, 0xAC, 0x0C, 0xAC, 0x77, 0xE0, 0x64] hash = bytearray(b"308202e4308201cc020101300d06092a864886f70d010105050030373116301406035504030c0d416e64726f69642044656275673110300e060355040a0c07416e64726f6964310b30090603550406130255533020170d3231303330363134333034385a180f32303531303232373134333034385a30373116301406035504030c0d416e64726f69642044656275673110300e060355040a0c07416e64726f6964310b300906035504061302555330820122300d06092a864886f70d01010105000382010f003082010a0282010100cbf2b09e4308ebb459e8841e5a7b920497fef2b349e80648f7eb35f48d40a75e7ce7945b8b42d197bec0bf177e6c9899ed707dcc4a726cb14c1a69b0c4a02474806fa73cfb10e10f7b1665021c24762b6edad65ca63cea3c72e0d4e4ca3f98301173eec3254337af1f5a11f779ecbe04d1b74d53f5835e011222155a56f97e00d75374cd93080dfa087cd356a99fe1eebf5d6d5e31846aad5252c3a17a4656e2e210ce1c7aa4d147fb8cf440a50add61bbb2ec299a2e0dab0b4504796ac3a899da553ab1d83576691ab23409d18398014b3b5eaf12e83f4d99aa09e1e4e4cae133530730c1133da2b3dee37b58eb1a5795b221ec5a8830731a41167d295f9e1b0203010001300d06092a864886f70d010105050003820101000e4740235e9cf2be33de3e06d777139cbbc5cf0622285c17da04697b8067318aaf8df0fbb4d3166f293ea15aa2592f06eb6929af063722ac9f30ad85e2c087564931d6ac65fcd5fbc864b3dc9841e039c6e1d5fbc5c2f8adf90a547bc4ebc07d387914db24451c2cc89925359bd3bb0750c7aabf9d743b1893e98bbc8ff74b24fc0b4be2dbaaf1c917bba01496d0617ffc3a4a8b7a6e79a3036298a6ebf57bb00001e43a0b242864eebb0fcec9e323144d4447c878430f18e6e358ad97566fa04d1f07b171c1476c9af5a1eba0bf6616e219c0b9e1299d09fecded24a880397f92e0f99d8951228c7770c184fd77adff943bfc8b6aa524c5f0a6d7686fe35486") # t = 55 # t = (t >> 3) & 0x1F | (t << 5) # t &= 0xff # print(t) # t |= (t & 0xf) << 8 # t = (t << 3) & 0x1F | (t >> 5) # t &= 0xff # print(t) for i in range(0, 42): arr[i] |= (arr[i] & 0xf) << 8 for i in range(0, 42): arr[i] = ((arr[i] << 3) | (arr[i] >> 5)) & 0xff for i in range(0, 42): arr[i] ^= hash[i * 27 + 327] + i print(i, chr(arr[i])) print("".join([chr(i) for i in arr]))
ooo
简单异或
异或key为第7,8,9位字符异或
直接爆破
# -*- coding:utf-8 -*- """ @Author: Mas0n @File: dhb3.py @Time: 2021-10-31 17:18 @Desc: It's all about getting better. """ data = [0x00000006, 0x0000010C, 0x00000201, 0x00000307, 0x0000041B, 0x00000551, 0x00000653, 0x00000706, 0x00000853, 0x00000955, 0x00000A56, 0x00000B56, 0x00000C53, 0x00000D4D, 0x00000E55, 0x00000F50, 0x00001001, 0x00001154, 0x0000124D, 0x00001354, 0x00001457, 0x00001557, 0x00001602, 0x0000174D, 0x00001852, 0x00001957, 0x00001A58, 0x00001B02, 0x00001C4D, 0x00001D02, 0x00001E57, 0x00001F51, 0x00002051, 0x00002150, 0x00002252, 0x00002356, 0x00002406, 0x00002506, 0x00002657, 0x00002701, 0x00002804, 0x0000291D] for m in range(127): arr = [chr((j ^ m) & 0xff) for j in data] flag = "".join(arr) if flag.startswith("flag{"): print(flag)
mod
魔改base64
去除花指令后
int __cdecl sub_491320(int a1) { int result; // eax char *v2; // [esp+10h] [ebp-2Ch] char *v3; // [esp+14h] [ebp-28h] signed int v4; // [esp+1Ch] [ebp-20h] int i; // [esp+28h] [ebp-14h] v4 = strlen(input); dword_4954A0 = v4; if ( v4 % 3 == 1 ) { v3 = &input[dword_4954A0++]; sub_491020(v3, "="); } else if ( v4 % 3 != 2 ) { goto LABEL_6; } v2 = &input[dword_4954A0++]; sub_491020(v2, "="); LABEL_6: for ( i = 0; i < dword_4954A0; i += 3 ) sub_4911A0((int)input, i, a1); // 主逻辑 result = v4 / 3; if ( v4 % 3 == 1 ) return sub_491020((char *)(a1 + 4 * (v4 / 3)), "=="); if ( v4 % 3 == 2 ) return sub_491020((char *)(a1 + 4 * (v4 / 3)), "="); return result; }
主逻辑在sub_4911A0
上脚本,z3求解
# -*- coding:utf-8 -*- """ @Author: Mas0n @File: test14.py @Time: 2021-10-31 15:47 @Desc: It's all about getting better. """ import z3 aAbcdfegh1jklrs = 'ABCDFEGH1JKLRSTMNP0VWQUXY2a8cdefijklmnopghwxyqrstuvzOIZ34567b9+/' a3 = "2aYcdfL2fS1BTMMF1RSeMTTASS1OJ8RHTJdBYJ2STJfNMSMAYcKUJddp" flag = "" for i in range(0, len(a3), 4): i0 = aAbcdfegh1jklrs.index(a3[i + 0]) i1 = aAbcdfegh1jklrs.index(a3[i + 1]) i2 = aAbcdfegh1jklrs.index(a3[i + 2]) i3 = aAbcdfegh1jklrs.index(a3[i + 3]) a1 = [z3.BitVec("a{}".format(j), 8) for j in range(3)] sol = z3.Solver() sol.add(((4 * (a1[2] & 3)) | a1[1] & 0x30 | a1[0] & 0xC0) == i0 << 2) sol.add(((4 * (a1[0] & 3)) | a1[2] & 0x30 | a1[1] & 0xC0) == i1 << 2) sol.add(((4 * (a1[1] & 3)) | a1[0] & 0x30 | a1[2] & 0xC0) == i2 << 2) sol.add((a1[2] & 12 | (4 * a1[1]) & 0x30 | (16 * a1[0]) & 0xC0) == i3 << 2) assert sol.check() == z3.sat solve = sol.model() flag += "".join([chr(solve.eval(j).as_long()) for j in a1]) print(flag) # a3[4 * (i / 3)] = aAbcdfegh1jklrs[((4 * (a1[i + 2] & 3)) | a1[i + 1] & 0x30 | a1[i] & 0xC0) >> 2] # a3[4 * (i / 3) + 1] = aAbcdfegh1jklrs[((4 * (a1[i] & 3)) | a1[i + 2] & 0x30 | a1[i + 1] & 0xC0) >> 2] # a3[4 * (i / 3) + 2] = aAbcdfegh1jklrs[((4 * (a1[i + 1] & 3)) | a1[i] & 0x30 | a1[i + 2] & 0xC0) >> 2] # a3[4 * (i / 3) + 3] = aAbcdfegh1jklrs[(a1[i + 2] & 12 | (4 * a1[i + 1]) & 0x30 | (16 * a1[i]) & 0xC0) >> 2]
发表回复