上海省赛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]