-
-
[原创] SWPUCTF 2019 easyRE
-
发表于: 2022-3-11 10:24 9074
-
main函数:
首先调用sub_40EF90
进行check:
搜了一下官方文档,发现ProcessDebugPort就是用来检测程序是否处于调试状态的:
这里crack很简单,动态调试单步来到这个位置,这里是压入三个参数的,一般就是main函数的入口了:
call完EF90之后会有个关键跳,这里jmp实现的话就直接退出程序了,直接nop掉jmp即可:
Patch完之后重新载入x64dbg,此时就可以正常调试了:
当然了这个调试状态检测我们是可以绕过的,因为是在检测调试之后再执行真正的代码,所以可以先直接运行程序,然后用附加程序,这时候程序已经运行到输入flag的位置了,附加时已经过了检测函数,所以也可以正常进行调试:
往下来到sub_401FE0,发现有个EASYRE::vftable
虚函数表,然后往下对内存进行赋值,总共20个字节,往下还有个内存复制,也是20个字节:
字符串定位到sub_40F150,传入的flag
通过sub_4024B0
进行校验,条件成立才能输出Congratulations:
sub_4024B0,虚函数调用的特征:
根据虚表简化得到:
将字符串Ncg复制到v8然后将v8的值逐个异或0x10:
得到一个正则表达式:^swpuctf\\{\\w{4}\\-\\w{4}\\-\\w{4}\\-\\w{4}\\-\\w{4}\\}
为flag的格式
那么可以得到第一个函数就是校验flag的格式,dbg中输入:swpuctf{1234-5678-9012-3456-7890}
,此时跳转已经不实现:
先看到最后一个函数,需要让if成立,使得result=1,才能最终输出Congratulations
this[52]
在sub_401FE0
中进行了赋值,需要注意i从0开始经过40次循环,回到sub_401FE0的初始化,发现还存在一个字符串:03\"3 0 203\" $
,说明还存在一个需要比较的结果:
来到关键的处理函数:
同样查表:
v10 = this[2] + 5 * a2 + 8;
,a2
作为下标,通过-
分割开取值,此时外层循环中i为0
,所以传入的a2
也是0
,在x64dbg中存储为ecx
,所以此时v10
指向的就是flag
的第一部分1234
:
do-while循环中,明显可以看出是针对单字符进行处理的,v2作为索引,每次取一个字符放到v4中,v3作为循环次数,每循环一次减一:
这里只写了rcl dl,1
x64dbg调试的时候,可以发现rcl下面存在一个jb指令,这个指令受CF位的影响,当CF为1时跳转指令成立,这里跟dl的值有关,当dl产生进位时CF置1,跳转成立,出循环:
经测试可以发现当0x31左移3次时产生进位,所以此时ebx值为3,那么ebx中记录的就是左移的位数:
同理,往下对0x31进行右移,当产生进位时CF置1,跳出循环,ebx记录右移次数减一的值:
这一部分在IDA反编译的不太一样,按照动态调试中体现的汇编更容易理解:
4次循环之后得到,分别对应0x31 0x32 0x33 0x34
,左边的为左移到进位的次数;右边为右移次数减一,这么理解比较奇怪,我觉得可以理解为从右边0的个数:
如:0x31
,二进制为 0011 0001
,所以此时右边0的个数为0
0x32
,二进制为 0011 0010
,所以此时右边0的个数为1
0x34
,二进制为 0011 0100
,所以此时右边0的个数为2
第二个循环:
根据第一个循环简化,最终生成三个值,处理每个字符的结果是独立进行计算的,跟位置和前后字符无关,互不影响:
这里IDA反编译的res2应该是少了一个移位运算,第一步
运行之后得到:
往下走到最后一个处理的函数sub_4028A0
,存在while循环,这里while循环的条件为sub_402E00
传入v2之后的结果,大致理解为flag的结束,说明while循环针对flag进行遍历的,每个while循环对单个字符进行处理,跟之前的处理一样,不受位置和前后字符值的影响:
在while中存在一个for循环,该循环分为上下两部分,前四次循环会对v15和v15+i+20进行运算处理,后四次循环只对v15进行处理,这里sub_402DC0指向处理后的字符以及sub_402730处理后的结果:
执行sub_402DC0
后返回0xDC41D8
:
根据0xDC41D8指向的内存,可以简化该循环:
可以发现v15 + i + 20
是直接赋值,而这里i注意是跟循环有关,那么每个for循环会生成4个值,而v15注意到DWORD指针,每个for循环也是生成一个DWORD类型的数据,可以判断出while循环应该是进行5次,每次对一部分flag进行处理,最终会得到一个长度为40的结果,调用sub_402A00进行比较
第一个循环解决之后得到两个值,顺带发现了最终对比的数据就是前面初始化值的数据
第一个循环:
第二次循环结束,发现第一部分是会受其他循环影响的,而第二部分是不受其他循环影响的:
当i>=4时,是直接取res1:
和res2进行运算:
最终的比较:
分析到这里,整个程序流程基本上就都了解了:
第一部分check_1左移进位位数,check_0计算右边0的个数,然后generate计算sub_402730后面的结果,并将三个结果作为list返回:
第二部分就是通过03\"3 0 203\" $
进行字符串排除,这里可以判断flag的范围应该是A-Za-z0-9
,通过前面的分析知道每个字符运算的结果互相独立,但是这里可能存在重复的情况,所以先用set
去重,然后对set
中每个元素作为key
,创建一个字典,如果check
的结果为key
则加入该key
的value
中,最后返回结果:
第三部分,test_1作为for循环中前四部分的计算,这里需要注意v14要代入并返回,经过8次运算后,将结果或成一个DWORD值,与first_part对应的DWORD进行对比,如果相等则返回此时循环的4个字符,这里是可以得到唯一值的,最终拼接得到flag:
flag:
提交BUUCTF:
完整exp:
优化:
int
__cdecl main(
int
argc, const char
*
*
argv, const char
*
*
envp)
{
_DWORD v4[
28
];
/
/
[esp
-
6Ch
] [ebp
-
F8h] BYREF
_DWORD
*
v5;
/
/
[esp
+
4h
] [ebp
-
88h
]
_DWORD
*
v6;
/
/
[esp
+
8h
] [ebp
-
84h
]
int
v7;
/
/
[esp
+
Ch] [ebp
-
80h
]
char v8[
108
];
/
/
[esp
+
10h
] [ebp
-
7Ch
] BYREF
int
v9;
/
/
[esp
+
88h
] [ebp
-
4h
]
if
( sub_40EF90() )
return
1
;
sub_4026C0(
0x6Cu
);
sub_401FE0(v4[
27
], v5);
v9
=
0
;
v6
=
v4;
sub_40F360(v8);
sub_40F080(v4[
0
], v4[
1
]);
v5
=
v4;
sub_40F360(v8);
sub_40F150(argc, (
int
)argv);
v7
=
0
;
v9
=
-
1
;
sub_4021C0(v8);
return
v7;
}
int
__cdecl main(
int
argc, const char
*
*
argv, const char
*
*
envp)
{
_DWORD v4[
28
];
/
/
[esp
-
6Ch
] [ebp
-
F8h] BYREF
_DWORD
*
v5;
/
/
[esp
+
4h
] [ebp
-
88h
]
_DWORD
*
v6;
/
/
[esp
+
8h
] [ebp
-
84h
]
int
v7;
/
/
[esp
+
Ch] [ebp
-
80h
]
char v8[
108
];
/
/
[esp
+
10h
] [ebp
-
7Ch
] BYREF
int
v9;
/
/
[esp
+
88h
] [ebp
-
4h
]
if
( sub_40EF90() )
return
1
;
sub_4026C0(
0x6Cu
);
sub_401FE0(v4[
27
], v5);
v9
=
0
;
v6
=
v4;
sub_40F360(v8);
sub_40F080(v4[
0
], v4[
1
]);
v5
=
v4;
sub_40F360(v8);
sub_40F150(argc, (
int
)argv);
v7
=
0
;
v9
=
-
1
;
sub_4021C0(v8);
return
v7;
}
BOOL
sub_40EF90()
{
HANDLE v0;
/
/
eax
NTSTATUS (__stdcall
*
NtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
/
/
[esp
+
0h
] [ebp
-
14h
]
HMODULE hModule;
/
/
[esp
+
4h
] [ebp
-
10h
]
int
v4;
/
/
[esp
+
Ch] [ebp
-
8h
] BYREF
v4
=
0
;
hModule
=
LoadLibraryA(
"Ntdll.dll"
);
NtQueryInformationProcess
=
(NTSTATUS (__stdcall
*
)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG))GetProcAddress(hModule,
"NtQueryInformationProcess"
);
v0
=
GetCurrentProcess();
NtQueryInformationProcess(v0, ProcessDebugPort, &v4,
4
,
0
);
return
v4 !
=
0
;
}
BOOL
sub_40EF90()
{
HANDLE v0;
/
/
eax
NTSTATUS (__stdcall
*
NtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
/
/
[esp
+
0h
] [ebp
-
14h
]
HMODULE hModule;
/
/
[esp
+
4h
] [ebp
-
10h
]
int
v4;
/
/
[esp
+
Ch] [ebp
-
8h
] BYREF
v4
=
0
;
hModule
=
LoadLibraryA(
"Ntdll.dll"
);
NtQueryInformationProcess
=
(NTSTATUS (__stdcall
*
)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG))GetProcAddress(hModule,
"NtQueryInformationProcess"
);
v0
=
GetCurrentProcess();
NtQueryInformationProcess(v0, ProcessDebugPort, &v4,
4
,
0
);
return
v4 !
=
0
;
}
_DWORD
*
__thiscall sub_401FE0(_DWORD
*
this)
{
int
i;
/
/
[esp
+
4h
] [ebp
-
14h
]
*
this
=
&EASYRE::`vftable';
this[
1
]
=
0
;
*
((_BYTE
*
)this
+
52
)
=
8
;
*
((_BYTE
*
)this
+
53
)
=
0xEA
;
*
((_BYTE
*
)this
+
54
)
=
0x58
;
*
((_BYTE
*
)this
+
55
)
=
0xDE
;
*
((_BYTE
*
)this
+
56
)
=
0x94
;
*
((_BYTE
*
)this
+
57
)
=
0xD0
;
*
((_BYTE
*
)this
+
58
)
=
0x3B
;
*
((_BYTE
*
)this
+
59
)
=
0xBE
;
*
((_BYTE
*
)this
+
60
)
=
0x88
;
*
((_BYTE
*
)this
+
61
)
=
0xD4
;
*
((_BYTE
*
)this
+
62
)
=
0x32
;
*
((_BYTE
*
)this
+
63
)
=
0xB6
;
*
((_BYTE
*
)this
+
64
)
=
0x14
;
*
((_BYTE
*
)this
+
65
)
=
0x82
;
*
((_BYTE
*
)this
+
66
)
=
0xB7
;
*
((_BYTE
*
)this
+
67
)
=
0xAF
;
*
((_BYTE
*
)this
+
68
)
=
0x14
;
*
((_BYTE
*
)this
+
69
)
=
0x54
;
*
((_BYTE
*
)this
+
70
)
=
0x7F
;
*
((_BYTE
*
)this
+
71
)
=
0xCF
;
qmemcpy(this
+
18
,
" 03\"3 0 203\" $ "
,
20
);
sub_4030A0(this
+
23
);
sub_402DE0(this
+
26
);
for
( i
=
0
; i <
40
;
+
+
i )
*
((_BYTE
*
)this
+
i
+
12
)
=
0
;
return
this;
}
_DWORD
*
__thiscall sub_401FE0(_DWORD
*
this)
{
int
i;
/
/
[esp
+
4h
] [ebp
-
14h
]
*
this
=
&EASYRE::`vftable';
this[
1
]
=
0
;
*
((_BYTE
*
)this
+
52
)
=
8
;
*
((_BYTE
*
)this
+
53
)
=
0xEA
;
*
((_BYTE
*
)this
+
54
)
=
0x58
;
*
((_BYTE
*
)this
+
55
)
=
0xDE
;
*
((_BYTE
*
)this
+
56
)
=
0x94
;
*
((_BYTE
*
)this
+
57
)
=
0xD0
;
*
((_BYTE
*
)this
+
58
)
=
0x3B
;
*
((_BYTE
*
)this
+
59
)
=
0xBE
;
*
((_BYTE
*
)this
+
60
)
=
0x88
;
*
((_BYTE
*
)this
+
61
)
=
0xD4
;
*
((_BYTE
*
)this
+
62
)
=
0x32
;
*
((_BYTE
*
)this
+
63
)
=
0xB6
;
*
((_BYTE
*
)this
+
64
)
=
0x14
;
*
((_BYTE
*
)this
+
65
)
=
0x82
;
*
((_BYTE
*
)this
+
66
)
=
0xB7
;
*
((_BYTE
*
)this
+
67
)
=
0xAF
;
*
((_BYTE
*
)this
+
68
)
=
0x14
;
*
((_BYTE
*
)this
+
69
)
=
0x54
;
*
((_BYTE
*
)this
+
70
)
=
0x7F
;
*
((_BYTE
*
)this
+
71
)
=
0xCF
;
qmemcpy(this
+
18
,
" 03\"3 0 203\" $ "
,
20
);
sub_4030A0(this
+
23
);
sub_402DE0(this
+
26
);
for
( i
=
0
; i <
40
;
+
+
i )
*
((_BYTE
*
)this
+
i
+
12
)
=
0
;
return
this;
}
int
sub_40F150(
int
a1,
int
a2, ...)
{
int
v2;
/
/
eax
int
v3;
/
/
eax
int
result;
/
/
eax
int
v5;
/
/
eax
int
v6[
10
];
/
/
[esp
+
Ch] [ebp
-
38h
] BYREF
int
v7;
/
/
[esp
+
40h
] [ebp
-
4h
]
va_list va;
/
/
[esp
+
54h
] [ebp
+
10h
] BYREF
va_start(va, a2);
v7
=
0
;
v6[
0
]
=
0
;
v6[
1
]
=
0
;
v6[
2
]
=
0
;
v6[
3
]
=
0
;
v6[
4
]
=
0
;
v6[
5
]
=
0
;
v6[
6
]
=
0
;
v6[
7
]
=
0
;
v6[
8
]
=
0
;
v6[
9
]
=
0
;
v2
=
sub_40F5B0(std::cout,
"Please input your flag : "
);
std::ostream::operator<<(v2, sub_40F8F0);
sub_40F930(std::cin, flag);
if
( sub_4024B0(flag) )
{
v3
=
sub_40F5B0(std::cout, &unk_4122F0);
/
/
Congratulations
std::ostream::operator<<(v3, sub_40F8F0);
v7
=
-
1
;
sub_4021C0(va);
result
=
1
;
}
else
{
v5
=
sub_40F5B0(std::cout, &unk_41231C);
/
/
I'm sorry
std::ostream::operator<<(v5, sub_40F8F0);
v7
=
-
1
;
sub_4021C0(va);
result
=
0
;
}
return
result;
}
int
sub_40F150(
int
a1,
int
a2, ...)
{
int
v2;
/
/
eax
int
v3;
/
/
eax
int
result;
/
/
eax
int
v5;
/
/
eax
int
v6[
10
];
/
/
[esp
+
Ch] [ebp
-
38h
] BYREF
int
v7;
/
/
[esp
+
40h
] [ebp
-
4h
]
va_list va;
/
/
[esp
+
54h
] [ebp
+
10h
] BYREF
va_start(va, a2);
v7
=
0
;
v6[
0
]
=
0
;
v6[
1
]
=
0
;
v6[
2
]
=
0
;
v6[
3
]
=
0
;
v6[
4
]
=
0
;
v6[
5
]
=
0
;
v6[
6
]
=
0
;
v6[
7
]
=
0
;
v6[
8
]
=
0
;
v6[
9
]
=
0
;
v2
=
sub_40F5B0(std::cout,
"Please input your flag : "
);
std::ostream::operator<<(v2, sub_40F8F0);
sub_40F930(std::cin, flag);
if
( sub_4024B0(flag) )
{
v3
=
sub_40F5B0(std::cout, &unk_4122F0);
/
/
Congratulations
std::ostream::operator<<(v3, sub_40F8F0);
v7
=
-
1
;
sub_4021C0(va);
result
=
1
;
}
else
{
v5
=
sub_40F5B0(std::cout, &unk_41231C);
/
/
I'm sorry
std::ostream::operator<<(v5, sub_40F8F0);
v7
=
-
1
;
sub_4021C0(va);
result
=
0
;
}
return
result;
}
BOOL
__thiscall sub_4024B0(_DWORD
*
this,
int
flag)
{
BOOL
result;
/
/
eax
this[
2
]
=
flag;
result
=
0
;
if
( (
*
(
int
(__thiscall
*
*
)(_DWORD
*
))(
*
this
+
0xC
))(this) )
{
(
*
(void (__thiscall
*
*
)(_DWORD
*
))(
*
this
+
0x18
))(this);
if
( (
*
(
int
(__thiscall
*
*
)(_DWORD
*
))(
*
this
+
0x28
))(this) )
result
=
1
;
}
return
result;
}
BOOL
__thiscall sub_4024B0(_DWORD
*
this,
int
flag)
{
BOOL
result;
/
/
eax
this[
2
]
=
flag;
result
=
0
;
if
( (
*
(
int
(__thiscall
*
*
)(_DWORD
*
))(
*
this
+
0xC
))(this) )
{
(
*
(void (__thiscall
*
*
)(_DWORD
*
))(
*
this
+
0x18
))(this);
if
( (
*
(
int
(__thiscall
*
*
)(_DWORD
*
))(
*
this
+
0x28
))(this) )
result
=
1
;
}
return
result;
}
BOOL
__thiscall sub_4024B0(_DWORD
*
this,
int
flag)
{
BOOL
result;
/
/
eax
this[
2
]
=
flag;
result
=
0
;
if
( sub_402500(flag) )
{
sub_4026E0();
if
( sub_402A00() )
result
=
1
;
}
return
result;
}
BOOL
__thiscall sub_4024B0(_DWORD
*
this,
int
flag)
{
BOOL
result;
/
/
eax
this[
2
]
=
flag;
result
=
0
;
if
( sub_402500(flag) )
{
sub_4026E0();
if
( sub_402A00() )
result
=
1
;
}
return
result;
}
int
__thiscall sub_402500(const char
*
*
this)
{
int
v2;
/
/
[esp
+
Ch] [ebp
-
B0h]
unsigned
int
v3;
/
/
[esp
+
14h
] [ebp
-
A8h]
int
i;
/
/
[esp
+
24h
] [ebp
-
98h
]
char v6[
56
];
/
/
[esp
+
30h
] [ebp
-
8Ch
] BYREF
char v7[
20
];
/
/
[esp
+
68h
] [ebp
-
54h
] BYREF
char v8[
48
];
/
/
[esp
+
7Ch
] [ebp
-
40h
] BYREF
int
v9;
/
/
[esp
+
B8h] [ebp
-
4h
]
v3
=
(unsigned
int
)&this[
2
][strlen(this[
2
])];
strcpy(v8,
"Ncg`esdvLkLgk$mL=Lgk$mL=Lgk$mL=Lgk$mL=Lgk$mLm"
);
sub_4026C0(v6,
0x38u
);
sub_402B00();
v9
=
0
;
for
( i
=
0
; i <
45
;
+
+
i )
v8[i] ^
=
0x10u
;
sub_4026C0(v7,
0x14u
);
sub_402A70(v8,
1
);
LOBYTE(v9)
=
1
;
v2
=
(unsigned __int8)sub_404260(this[
2
], v3, v6, v7,
0
);
LOBYTE(v9)
=
0
;
sub_402A50(v7);
v9
=
-
1
;
sub_4026A0();
return
v2;
}
int
__thiscall sub_402500(const char
*
*
this)
{
int
v2;
/
/
[esp
+
Ch] [ebp
-
B0h]
unsigned
int
v3;
/
/
[esp
+
14h
] [ebp
-
A8h]
int
i;
/
/
[esp
+
24h
] [ebp
-
98h
]
char v6[
56
];
/
/
[esp
+
30h
] [ebp
-
8Ch
] BYREF
char v7[
20
];
/
/
[esp
+
68h
] [ebp
-
54h
] BYREF
char v8[
48
];
/
/
[esp
+
7Ch
] [ebp
-
40h
] BYREF
int
v9;
/
/
[esp
+
B8h] [ebp
-
4h
]
v3
=
(unsigned
int
)&this[
2
][strlen(this[
2
])];
strcpy(v8,
"Ncg`esdvLkLgk$mL=Lgk$mL=Lgk$mL=Lgk$mL=Lgk$mLm"
);
sub_4026C0(v6,
0x38u
);
sub_402B00();
v9
=
0
;
for
( i
=
0
; i <
45
;
+
+
i )
v8[i] ^
=
0x10u
;
sub_4026C0(v7,
0x14u
);
sub_402A70(v8,
1
);
LOBYTE(v9)
=
1
;
v2
=
(unsigned __int8)sub_404260(this[
2
], v3, v6, v7,
0
);
LOBYTE(v9)
=
0
;
sub_402A50(v7);
v9
=
-
1
;
sub_4026A0();
return
v2;
}
s
=
"Ncg`esdvLkLgk$mL=Lgk$mL=Lgk$mL=Lgk$mL=Lgk$mLm"
s2
=
[]
for
i
in
range
(
0
,
len
(s)):
s2.append(
chr
(
ord
(s[i]) ^
0x10
))
print
(''.join(i
for
i
in
s2))
# ^swpuctf\\{\\w{4}\\-\\w{4}\\-\\w{4}\\-\\w{4}\\-\\w{4}\\}
s
=
"Ncg`esdvLkLgk$mL=Lgk$mL=Lgk$mL=Lgk$mL=Lgk$mLm"
s2
=
[]
for
i
in
range
(
0
,
len
(s)):
s2.append(
chr
(
ord
(s[i]) ^
0x10
))
print
(''.join(i
for
i
in
s2))
# ^swpuctf\\{\\w{4}\\-\\w{4}\\-\\w{4}\\-\\w{4}\\-\\w{4}\\}
if
( sub_402A00() )
result
=
1
;
if
( sub_402A00() )
result
=
1
;
int
__thiscall sub_402A00(unsigned __int8
*
this)
{
int
i;
/
/
[esp
+
4h
] [ebp
-
4h
]
for
( i
=
0
; i <
40
;
+
+
i )
{
if
( this[i
+
52
] !
=
this[i
+
12
] )
return
0
;
}
return
1
;
}
int
__thiscall sub_402A00(unsigned __int8
*
this)
{
int
i;
/
/
[esp
+
4h
] [ebp
-
4h
]
for
( i
=
0
; i <
40
;
+
+
i )
{
if
( this[i
+
52
] !
=
this[i
+
12
] )
return
0
;
}
return
1
;
}
*
((_BYTE
*
)this
+
52
)
=
8
;
*
((_BYTE
*
)this
+
53
)
=
0xEA
;
*
((_BYTE
*
)this
+
54
)
=
0x58
;
*
((_BYTE
*
)this
+
55
)
=
0xDE
;
*
((_BYTE
*
)this
+
56
)
=
0x94
;
*
((_BYTE
*
)this
+
57
)
=
0xD0
;
*
((_BYTE
*
)this
+
58
)
=
0x3B
;
*
((_BYTE
*
)this
+
59
)
=
0xBE
;
*
((_BYTE
*
)this
+
60
)
=
0x88
;
*
((_BYTE
*
)this
+
61
)
=
0xD4
;
*
((_BYTE
*
)this
+
62
)
=
0x32
;
*
((_BYTE
*
)this
+
63
)
=
0xB6
;
*
((_BYTE
*
)this
+
64
)
=
0x14
;
*
((_BYTE
*
)this
+
65
)
=
0x82
;
*
((_BYTE
*
)this
+
66
)
=
0xB7
;
*
((_BYTE
*
)this
+
67
)
=
0xAF
;
*
((_BYTE
*
)this
+
68
)
=
0x14
;
*
((_BYTE
*
)this
+
69
)
=
0x54
;
*
((_BYTE
*
)this
+
70
)
=
0x7F
;
*
((_BYTE
*
)this
+
71
)
=
0xCF
;
qmemcpy(this
+
18
,
" 03\"3 0 203\" $ "
,
20
);
*
((_BYTE
*
)this
+
52
)
=
8
;
*
((_BYTE
*
)this
+
53
)
=
0xEA
;
*
((_BYTE
*
)this
+
54
)
=
0x58
;
*
((_BYTE
*
)this
+
55
)
=
0xDE
;
*
((_BYTE
*
)this
+
56
)
=
0x94
;
*
((_BYTE
*
)this
+
57
)
=
0xD0
;
*
((_BYTE
*
)this
+
58
)
=
0x3B
;
*
((_BYTE
*
)this
+
59
)
=
0xBE
;
*
((_BYTE
*
)this
+
60
)
=
0x88
;
*
((_BYTE
*
)this
+
61
)
=
0xD4
;
*
((_BYTE
*
)this
+
62
)
=
0x32
;
*
((_BYTE
*
)this
+
63
)
=
0xB6
;
*
((_BYTE
*
)this
+
64
)
=
0x14
;
*
((_BYTE
*
)this
+
65
)
=
0x82
;
*
((_BYTE
*
)this
+
66
)
=
0xB7
;
*
((_BYTE
*
)this
+
67
)
=
0xAF
;
*
((_BYTE
*
)this
+
68
)
=
0x14
;
*
((_BYTE
*
)this
+
69
)
=
0x54
;
*
((_BYTE
*
)this
+
70
)
=
0x7F
;
*
((_BYTE
*
)this
+
71
)
=
0xCF
;
qmemcpy(this
+
18
,
" 03\"3 0 203\" $ "
,
20
);
int
__thiscall sub_4026E0(void
*
this)
{
int
i;
/
/
[esp
+
4h
] [ebp
-
4h
]
for
( i
=
0
; i <
5
;
+
+
i )
(
*
(void (__thiscall
*
*
)(void
*
,
int
))(
*
(_DWORD
*
)this
+
0x1C
))(this, i);
/
/
return
(
*
(
int
(__thiscall
*
*
)(void
*
))(
*
(_DWORD
*
)this
+
0x24
))(this);
/
/
}
int
__thiscall sub_4026E0(void
*
this)
{
int
i;
/
/
[esp
+
4h
] [ebp
-
4h
]
for
( i
=
0
; i <
5
;
+
+
i )
(
*
(void (__thiscall
*
*
)(void
*
,
int
))(
*
(_DWORD
*
)this
+
0x1C
))(this, i);
/
/
return
(
*
(
int
(__thiscall
*
*
)(void
*
))(
*
(_DWORD
*
)this
+
0x24
))(this);
/
/
}
this
+
0x1c
-
> sub_402730
this
+
0x24
-
> sub_4028A0
this
+
0x1c
-
> sub_402730
this
+
0x24
-
> sub_4028A0
int
__thiscall sub_402730(_DWORD
*
this,
int
a2)
{
int
v2;
/
/
esi
int
v3;
/
/
ecx
unsigned __int8 v4;
/
/
al
char v6;
/
/
cf
char v7;
/
/
bl
char v8;
/
/
t2
int
v10;
/
/
[esp
+
Ch] [ebp
-
30h
]
int
i;
/
/
[esp
+
14h
] [ebp
-
28h
]
int
j;
/
/
[esp
+
1Ch
] [ebp
-
20h
]
int
v13;
/
/
[esp
+
20h
] [ebp
-
1Ch
] BYREF
int
v14;
/
/
[esp
+
24h
] [ebp
-
18h
]
int
v15;
/
/
[esp
+
28h
] [ebp
-
14h
]
int
v16;
/
/
[esp
+
2Ch
] [ebp
-
10h
]
int
v17;
/
/
[esp
+
30h
] [ebp
-
Ch]
int
v18;
/
/
[esp
+
34h
] [ebp
-
8h
]
v13
=
0
;
v14
=
0
;
v15
=
0
;
v16
=
0
;
v17
=
0
;
v18
=
0
;
v10
=
this[
2
]
+
5
*
a2
+
8
;
/
/
根据传入的a2取flag的各个部分
for
( i
=
0
; i <
4
;
+
+
i )
*
((_BYTE
*
)&v13
+
i)
=
*
(_BYTE
*
)(i
+
v10);
/
/
复制内存
v2
=
0
;
v3
=
4
;
do
{
v4
=
*
((_BYTE
*
)&v13
+
v2);
_DL
=
v4;
__asm { rcl dl,
1
}
*
((_BYTE
*
)&v15
+
v2)
=
1
;
v7
=
0
;
v6
=
0
;
do
{
v8
=
v6 <<
7
;
v6
=
v4 &
1
;
/
/
影响循环次数
v4
=
(v4 >>
1
) | v8;
+
+
v7;
}
while
( v6 );
*
((_BYTE
*
)&v16
+
v2
+
+
)
=
v7
-
1
;
-
-
v3;
}
while
( v3 );
for
( j
=
0
; j <
4
;
+
+
j )
{
*
((_BYTE
*
)&v14
+
j)
=
*
((_BYTE
*
)&v16
+
j)
+
*
((_BYTE
*
)&v15
+
j);
*
((_BYTE
*
)&v17
+
j)
=
*
((char
*
)&v13
+
j) <<
*
((_BYTE
*
)&v15
+
j);
*
((_BYTE
*
)&v18
+
j)
=
(
*
((char
*
)&v13
+
j) << (
8
-
*
((_BYTE
*
)&v16
+
j))) | ((unsigned __int8)(
*
((char
*
)&v13
+
j) >> (
8
-
*
((_BYTE
*
)&v15
+
j))) <<
*
((_BYTE
*
)&v15
+
j));
}
return
sub_402F80(&v13);
}
int
__thiscall sub_402730(_DWORD
*
this,
int
a2)
{
int
v2;
/
/
esi
int
v3;
/
/
ecx
unsigned __int8 v4;
/
/
al
char v6;
/
/
cf
char v7;
/
/
bl
char v8;
/
/
t2
int
v10;
/
/
[esp
+
Ch] [ebp
-
30h
]
int
i;
/
/
[esp
+
14h
] [ebp
-
28h
]
int
j;
/
/
[esp
+
1Ch
] [ebp
-
20h
]
int
v13;
/
/
[esp
+
20h
] [ebp
-
1Ch
] BYREF
int
v14;
/
/
[esp
+
24h
] [ebp
-
18h
]
int
v15;
/
/
[esp
+
28h
] [ebp
-
14h
]
int
v16;
/
/
[esp
+
2Ch
] [ebp
-
10h
]
int
v17;
/
/
[esp
+
30h
] [ebp
-
Ch]
int
v18;
/
/
[esp
+
34h
] [ebp
-
8h
]
v13
=
0
;
v14
=
0
;
v15
=
0
;
v16
=
0
;
v17
=
0
;
v18
=
0
;
v10
=
this[
2
]
+
5
*
a2
+
8
;
/
/
根据传入的a2取flag的各个部分
for
( i
=
0
; i <
4
;
+
+
i )
*
((_BYTE
*
)&v13
+
i)
=
*
(_BYTE
*
)(i
+
v10);
/
/
复制内存
v2
=
0
;
v3
=
4
;
do
{
v4
=
*
((_BYTE
*
)&v13
+
v2);
_DL
=
v4;
__asm { rcl dl,
1
}
*
((_BYTE
*
)&v15
+
v2)
=
1
;
v7
=
0
;
v6
=
0
;
do
{
v8
=
v6 <<
7
;
v6
=
v4 &
1
;
/
/
影响循环次数
v4
=
(v4 >>
1
) | v8;
+
+
v7;
}
while
( v6 );
*
((_BYTE
*
)&v16
+
v2
+
+
)
=
v7
-
1
;
-
-
v3;
}
while
( v3 );
for
( j
=
0
; j <
4
;
+
+
j )
{
*
((_BYTE
*
)&v14
+
j)
=
*
((_BYTE
*
)&v16
+
j)
+
*
((_BYTE
*
)&v15
+
j);
*
((_BYTE
*
)&v17
+
j)
=
*
((char
*
)&v13
+
j) <<
*
((_BYTE
*
)&v15
+
j);
*
((_BYTE
*
)&v18
+
j)
=
(
*
((char
*
)&v13
+
j) << (
8
-
*
((_BYTE
*
)&v16
+
j))) | ((unsigned __int8)(
*
((char
*
)&v13
+
j) >> (
8
-
*
((_BYTE
*
)&v15
+
j))) <<
*
((_BYTE
*
)&v15
+
j));
}
return
sub_402F80(&v13);
}
v2
=
0
;
v3
=
4
;
do
{
v4
=
*
((_BYTE
*
)&v13
+
v2);
/
/
取单个字符
_DL
=
v4;
__asm { rcl dl,
1
}
/
/
循环左移
*
((_BYTE
*
)&v15
+
v2)
=
1
;
v7
=
0
;
v6
=
0
;
do
{
v8
=
v6 <<
7
;
v6
=
v4 &
1
;
/
/
影响循环次数
v4
=
(v4 >>
1
) | v8;
+
+
v7;
}
while
( v6 );
*
((_BYTE
*
)&v16
+
v2
+
+
)
=
v7
-
1
;
-
-
v3;
}
while
( v3 );
v2
=
0
;
v3
=
4
;
do
{
v4
=
*
((_BYTE
*
)&v13
+
v2);
/
/
取单个字符
_DL
=
v4;
__asm { rcl dl,
1
}
/
/
循环左移
*
((_BYTE
*
)&v15
+
v2)
=
1
;
v7
=
0
;
v6
=
0
;
do
{
v8
=
v6 <<
7
;
v6
=
v4 &
1
;
/
/
影响循环次数
v4
=
(v4 >>
1
) | v8;
+
+
v7;
}
while
( v6 );
*
((_BYTE
*
)&v16
+
v2
+
+
)
=
v7
-
1
;
-
-
v3;
}
while
( v3 );
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!