begin
本人水平比较菜,做题只能靠玄学。做出来的时候也感觉有点点小不可思议。因为并没有对所有的流程都分析的很清楚。
反调试判断
在这一个位置有一个 int 2d 中断来验证
上网查了一下 int 2d的特性 是无调试的时候异常,有调试的时候正常运行。所以之后这个位置的
与 Vm0wd2QyUXlVWGw==
就是不会比对的,会直接跳到except处,因此程序会跳到40717d开始执行
算法部分
.text:00407010 mov esi, offset aKanxuecrackme2 ; "KanXueCrackMe2017"
.text:00407015 lea edi, [ebp+kanxue]
.text:00407018 movsd
.text:00407019 movsd
.text:0040701A movsd
.text:0040701B movsd
.text:0040701C movsw
.text:0040701E xor eax, eax
.text:00407020 lea edi, [ebp+var_3A]
.text:00407023 stosw
.text:00407025 lea eax, [ebp+kanxue]
.text:00407028 push eax
.text:00407029 lea eax, [ebp+var_D9F4]
.text:0040702F push eax
.text:00407030 call sub_4084A3 // 让KanXueCrackMe2017字符串在sub_4084A3这个函数进行加密
//-------------------------------------------------------------------------------
.text:0040717D mov esp, [ebp+ms_exc.old_esp] ; Exception handler 0 for function 406FC3
.text:00407180 lea eax, [ebp+var_38]
.text:00407183 push eax
.text:00407184 lea eax, [ebp+var_D9F4]
.text:0040718A push eax
.text:0040718B call sub_4084A3 // 让输入的字符串在sub_4084A3这个函数进行加密
关键就是在于 sub_4084A3 这个函数的分析,直接上伪代码把
void __stdcall sub_4084A3(int a1, const char *a2)
{
signed int i; // ebx@1
signed int v3; // edi@2
char v4; // al@3
const char *v5; // [sp+0h] [bp-4h]@1
signed int v6; // [sp+10h] [bp+Ch]@1
v5 = (const char *)malloc(3 * strlen(a2));
sub_40829C(a2, (int)v5); //将KanXueCrackMe2017字符串以及输入的字符串做一定的处理,加密后的值为 0-9A-H 这个范围
v6 = strlen(v5);
i = 0;
if ( v6 > 0 )
{
v3 = v6;
do
{
v4 = v5[i];
if ( v4 < '0' || v4 > '9' )
{
if ( v4 >= 'A' && v4 <= 'H' )
v3 = v4 - 55;
}
else
{
v3 = v4 - 0x30;
}
sub_4080DF(v3 / 3, v3 % 3 + 1, a1); //基于 0-9A-H 转化为 0-17 然后对一个数组进行处理。
++i;
}
while ( i < v6 );
}
free((void *)v5);
}
sub_4080DF位置 核心的操作就是 对 一个刚开始为 0至0x2f递增排列的数组按位置进行一个处理。
第一次是通过 KanXueCrackMe2017字符串 加密后的值 对0至0x2f递增排列的数组 按照一定规则进行打乱。
而 加密后的输入字符串 需要对这个数组进行还原回 0至0x2f递增排列的数组。
然后就所有人应该都卡在这里了,包括我。
对于sub_40829C的分析
在其中某个子函数中有中文,除法算法出错、模错误。。。等等中文,,推测可能是网上扒来的代码,应该不是自己写的一个很复杂加密。
尝试上网查过这个算法,但是失败了。
这一段最后是靠前后数据推理出来的。
刚开始测试输入的数据很大,然后没有思路,后来测试了一下小数
01 83
11 93
21 A3
31 B3
41 C3
51 D3
61 E3
71 F3
81 G3
91 H3
A1 04
02 G6
12 H6
13 7A
推理了一下就发现这个其实就是一个 18进制转为62进制的数
至于62进制,,由于输入的值是在0-9a-zA-Z 10+26+26=62 然后就是62进制,
使用python实现了一下还原脚本
ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
def base62_encode(num, alphabet=ALPHABET):
if (num == 0):
return alphabet[0]
arr = []
base = len(alphabet)
while num:
rem = num % base
num = num // base
arr.append(alphabet[rem])
arr.reverse()
return ''.join(arr)
a = int("46F9C1H147E25CFAE"[::-1],18)
print base62_encode(a)[::-1]
然后后面的就是 sub_4080DF
可以发现v4 = v5[i];
这个v4的范围是在A-H(0-17)
因为这个变换就是表的变换,而且只有18次 然后不嫌麻烦的我直接手动扣了一下数组。
map = [[0x06,0x07,0x00,0x01,0x02,0x03,0x04,0x05,0x08,0x09,0x0A,0x0B,0x22,0x23,0x24,0x0F,0x0E,0x11,0x12,0x13,0x14,0x15,0x0C,0x0D,0x16,0x17,0x10,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x18,0x19,0x1A,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F],
[0x04,0x05,0x06,0x07,0x00,0x01,0x02,0x03,0x08,0x09,0x0A,0x0B,0x18,0x19,0x1A,0x0F,0x24,0x11,0x12,0x13,0x14,0x15,0x22,0x23,0x0C,0x0D,0x0E,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x16,0x17,0x10,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F],
[0x02,0x03,0x04,0x05,0x06,0x07,0x00,0x01,0x08,0x09,0x0A,0x0B,0x16,0x17,0x10,0x0F,0x1A,0x11,0x12,0x13,0x14,0x15,0x18,0x19,0x22,0x23,0x24,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x0C,0x0D,0x0E,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F],
[0x10,0x11,0x12,0x03,0x04,0x05,0x06,0x07,0x0E,0x0F,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x2C,0x2D,0x2E,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x00,0x01,0x02,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x20,0x21,0x22,0x2F],
[0x2C,0x2D,0x2E,0x03,0x04,0x05,0x06,0x07,0x0C,0x0D,0x0E,0x0F,0x08,0x09,0x0A,0x0B,0x20,0x21,0x22,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x10,0x11,0x12,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x00,0x01,0x02,0x2F],
[0x20,0x21,0x22,0x03,0x04,0x05,0x06,0x07,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x08,0x09,0x00,0x01,0x02,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x2C,0x2D,0x2E,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x10,0x11,0x12,0x2F],
[0x00,0x01,0x1A,0x1B,0x1C,0x05,0x06,0x07,0x08,0x09,0x02,0x03,0x04,0x0D,0x0E,0x0F,0x16,0x17,0x10,0x11,0x12,0x13,0x14,0x15,0x18,0x19,0x2A,0x2B,0x2C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x0A,0x0B,0x0C,0x2D,0x2E,0x2F],
[0x00,0x01,0x2A,0x2B,0x2C,0x05,0x06,0x07,0x08,0x09,0x1A,0x1B,0x1C,0x0D,0x0E,0x0F,0x14,0x15,0x16,0x17,0x10,0x11,0x12,0x13,0x18,0x19,0x0A,0x0B,0x0C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x02,0x03,0x04,0x2D,0x2E,0x2F],
[0x00,0x01,0x0A,0x0B,0x0C,0x05,0x06,0x07,0x08,0x09,0x2A,0x2B,0x2C,0x0D,0x0E,0x0F,0x12,0x13,0x14,0x15,0x16,0x17,0x10,0x11,0x18,0x19,0x02,0x03,0x04,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x1A,0x1B,0x1C,0x2D,0x2E,0x2F],
[0x00,0x01,0x02,0x03,0x24,0x25,0x26,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x04,0x05,0x06,0x17,0x1E,0x1F,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x20,0x21,0x22,0x23,0x28,0x29,0x2A,0x27,0x14,0x15,0x16,0x2B,0x2C,0x2D,0x2E,0x2F],
[0x00,0x01,0x02,0x03,0x28,0x29,0x2A,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x24,0x25,0x26,0x17,0x1C,0x1D,0x1E,0x1F,0x18,0x19,0x1A,0x1B,0x20,0x21,0x22,0x23,0x14,0x15,0x16,0x27,0x04,0x05,0x06,0x2B,0x2C,0x2D,0x2E,0x2F],
[0x00,0x01,0x02,0x03,0x14,0x15,0x16,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x28,0x29,0x2A,0x17,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x18,0x19,0x20,0x21,0x22,0x23,0x04,0x05,0x06,0x27,0x24,0x25,0x26,0x2B,0x2C,0x2D,0x2E,0x2F],
[0x08,0x01,0x02,0x03,0x04,0x05,0x0E,0x0F,0x28,0x09,0x0A,0x0B,0x0C,0x0D,0x2E,0x2F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x00,0x19,0x1A,0x1B,0x1C,0x1D,0x06,0x07,0x26,0x27,0x20,0x21,0x22,0x23,0x24,0x25,0x18,0x29,0x2A,0x2B,0x2C,0x2D,0x1E,0x1F],
[0x28,0x01,0x02,0x03,0x04,0x05,0x2E,0x2F,0x18,0x09,0x0A,0x0B,0x0C,0x0D,0x1E,0x1F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x08,0x19,0x1A,0x1B,0x1C,0x1D,0x0E,0x0F,0x24,0x25,0x26,0x27,0x20,0x21,0x22,0x23,0x00,0x29,0x2A,0x2B,0x2C,0x2D,0x06,0x07],
[0x18,0x01,0x02,0x03,0x04,0x05,0x1E,0x1F,0x00,0x09,0x0A,0x0B,0x0C,0x0D,0x06,0x07,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x28,0x19,0x1A,0x1B,0x1C,0x1D,0x2E,0x2F,0x22,0x23,0x24,0x25,0x26,0x27,0x20,0x21,0x08,0x29,0x2A,0x2B,0x2C,0x2D,0x0E,0x0F],
[0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x12,0x13,0x14,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x1C,0x1D,0x1E,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x26,0x27,0x20,0x1F,0x0A,0x21,0x22,0x23,0x24,0x25,0x08,0x09,0x2E,0x2F,0x28,0x29,0x2A,0x2B,0x2C,0x2D],
[0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x1C,0x1D,0x1E,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x26,0x27,0x20,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x08,0x09,0x0A,0x1F,0x14,0x21,0x22,0x23,0x24,0x25,0x12,0x13,0x2C,0x2D,0x2E,0x2F,0x28,0x29,0x2A,0x2B],
[0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x26,0x27,0x20,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x08,0x09,0x0A,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x12,0x13,0x14,0x1F,0x1E,0x21,0x22,0x23,0x24,0x25,0x1C,0x1D,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x28,0x29]]
后面有一个地方是
.text:004071AB push eax
.text:004071AC call sub_40680C
.text:004071B1 cmp eax, 1
.text:004071B4 jnz short loc_4071D9
.text:004071B6 lea eax, [ebp+var_38]
.text:004071B9 lea edx, [eax+1]
.text:004071BC
.text:004071BC loc_4071BC: ; CODE XREF: sub_406FC3+1FEj
.text:004071BC mov cl, [eax]
.text:004071BE inc eax
.text:004071BF test cl, cl
.text:004071C1 jnz short loc_4071BC
.text:004071C3 sub eax, edx
.text:004071C5 cmp eax, 0Ch //输入长度为 12
.text:004071C8 jnz short loc_4071D9
要求输入的字符串为12字符的 所以我们需要缩短输入的长度。
a = [0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F]
import itertools
for x1,x2,x3 in itertools.product([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17], repeat=3) :
tmp = a
t1 = []
for i in range(len(a)):
t1.append(tmp[map[x1][i]])
t2 = []
for i in range(len(a)):
t2.append(t1[map[x2][i]])
if t2 == a:
print x1,x2
可以算出来 "0123456789ABCDEFGH" 逆推值为 "210543876BA9EDCHGF"
所以 EDAHE450C741GH441E11BH84 的逆推值为 46F911C144FG147E234CFADC (ps:EDAHE450C741GH441E11BH84是 sub_4080DF位置KanXueCrackMe2017字符串加密所得)
其中44和11因为相当于没加密可以去除,得到 46F9C1FG147E234CFADC
然后还是太长
再搜索能不能2字符有没有能用1字符替代的
def check(data):
newdata = ""
for i in data:
if i < 10:
newdata += chr(ord("0")+i)
else:
newdata += chr(ord("A")+i-10)
data = "46F911C144FG147E234CFADC" # 34 3
if newdata[:2] in data:
print newdata[:2],newdata[2]
# print newdata,
return newdata
import itertools
for x1,x2,x3 in itertools.product([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17], repeat=3) :
tmp = a
t1 = []
for i in range(len(a)):
t1.append(tmp[map[x1][i]])
t2 = []
for i in range(len(a)):
t2.append(t1[map[x2][i]])
t3 = []
for i in range(len(a)):
t3.append(t2[map[x3][i]])
if t3 == a:
# print x1,x2,x3
pt = check([x1,x2,x3])
#
#output
#34 3
#DC C
#FG F
#加上前面推理的 3-5 C-E F-H
因此46F9C1FG147E234CFADC 缩减为 46F9C1H147E25CFAE
跑前面的那个进制转换脚本就能够得到flag。
[培训]《安卓高级研修班(网课)》月薪三万计划,掌
握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法