加密手段:
数据结构分析:
逆向分析中的问题:
获得flag:
题目类型:
[[双进程保护]]
smc代码自修改
[[结构化异常SEH处理机制]]
Interrupt 3(03中断检测)
[[Merkle-Hellman背包加密]]

简介:
wp借鉴:
BUUCTF [SWPU2019]EasiestRe_皮皮蟹!的博客-CSDN博客
[SWPU2019]EasiestRe-cnblog - 自我摧残之策 - 博客园 (cnblogs.com)
[SWPU2019]EasiestRe - 编程猎人 (programminghunter.com)
[buuctf.reverse] 121-125_2021gkctf somuchcode-CSDN博客
446K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2U0L8X3u0D9L8$3N6K6i4K6u0W2j5$3!0E0i4K6u0r3K9r3q4J5L8h3!0F1K9h3y4S2x3e0q4Q4x3V1k6H3i4K6u0r3x3e0x3#2x3U0f1$3y4U0y4Q4x3X3g2Z5N6r3#2D9
f63K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3f1#2x3Y4m8G2K9X3W2W2i4K6u0W2j5$3&6Q4x3V1k6@1K9s2u0W2j5h3c8Q4x3X3b7I4y4e0R3H3y4U0V1I4i4K6u0V1x3g2)9J5k6o6q4Q4x3X3g2Z5N6r3#2D9i4K6t1K6y4o6p5@1y4o6l9H3z5e0q4Q4y4h3k6Q4y4f1u0K6N6%4m8#2i4K6g2p5i4K6u0V1k6h3q4K6K9h3g2K6N6s2u0W2
017K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2U0L8X3u0D9L8$3N6K6i4K6u0W2j5$3!0E0i4K6u0r3L8r3!0J5k6s2c8A6j5h3&6I4K9i4W2A6i4K6u0r3j5i4u0@1K9h3y4D9k6i4y4Q4x3V1j5I4y4U0b7#2y4U0j5J5y4W2)9J5k6h3S2@1L8h3H3`.
整体代码逆向分析:
整体父程序分析!
这里就是程序的输入入口了,但是真实的代码要运行以后通过触发int 3断点后才会出现!
根据父进程代码可知当程序中int 3 下面存在6个nop时将v16的数据写入!
成功写入!!

继续观察该函数发现:
继续一步步跟进函数发现!
sub_40247D(Str, v2, v1); -》sub_408860(Str, a2, a3);-》sub_40460B(a2, v10);
发现sub_40460B(a2, v10);这个函数内部也存在一个int 3 且下面的数据nop一共有30个!所以继续使用idapython脚本将程序patch!
成功patch

继续向下看:

分析一下sub_F7384B(v0); // 最后的函数,里面同样存在int 3,但是父进程只是发出了报错异常
为了不动态调试直接手动加一条jmp指令就可以了!!!

修改成功后的伪代码!
上面是加密过程!

下面是解密过程:

下面是分析背包解密了:

3. 获取私钥

解密脚本:
最后还有一个异或运算:

int
__cdecl main_0(
int
argc,
const
char
**argv,
const
char
**envp)
{
PVOID
lpBaseAddress;
...
if
( IsDebuggerPresent() )
{
falseflagfun();
return
0;
}
else
{
GetStartupInfoA(&StartupInfo);
GetModuleFileNameA(0, Filename, 0x104u);
if
( CreateProcessA(Filename, 0, 0, 0, 0, 3u, 0, 0, &StartupInfo, &ProcessInformation) )
{
v5 = 1;
LABEL_6:
while
( v5 )
{
dwContinueStatus = 0x10002;
WaitForDebugEvent(&DebugEvent, 0xFFFFFFFF);
switch
( DebugEvent.dwDebugEventCode )
{
case
1u:
if
( DebugEvent.u.Exception.ExceptionRecord.ExceptionCode == 0x80000003 )
{
v8 = 1;
dwContinueStatus = 65538;
lpBaseAddress = DebugEvent.u.Exception.ExceptionRecord.ExceptionAddress;
ReadProcessMemory(
ProcessInformation.hProcess,
DebugEvent.u.Exception.ExceptionRecord.ExceptionAddress,
Buffer,
0x23u,
NumberOfBytesRead);
if
( NumberOfBytesRead[0] )
{
for
( i = 1; i < 35 && Buffer[i] == 0x90; ++i )
;
}
if
( i == 1 )
v8 = 0;
if
( v8 )
{
switch
( i )
{
case
4:
Context.ContextFlags = 65543;
hThread = OpenThread(0x1FFFFFu, 0, DebugEvent.dwThreadId);
if
( !GetThreadContext(hThread, &Context) )
goto
LABEL_31;
++Context.Eip;
if
( SetThreadContext(hThread, &Context) )
{
dwContinueStatus = 65538;
CloseHandle(hThread);
}
goto
LABEL_33;
case
5:
LABEL_31:
ContinueDebugEvent(DebugEvent.dwProcessId, DebugEvent.dwThreadId, 0x80010001);
goto
LABEL_6;
case
7:
WriteProcessMemory(ProcessInformation.hProcess, lpBaseAddress, v16, 7u, NumberOfBytesWritten);
if
( NumberOfBytesWritten[0] == 7 )
{
ReadProcessMemory(ProcessInformation.hProcess, lpBaseAddress, Buffer, 7u, NumberOfBytesRead);
dwContinueStatus = 65538;
}
goto
LABEL_33;
case
30:
WriteProcessMemory(ProcessInformation.hProcess, lpBaseAddress, v15, 0x1Eu, NumberOfBytesWritten);
if
( NumberOfBytesWritten[0] == 30 )
dwContinueStatus = 65538;
goto
LABEL_33;
default
:
goto
LABEL_33;
...
}
int
__cdecl main_0(
int
argc,
const
char
**argv,
const
char
**envp)
{
PVOID
lpBaseAddress;
...
if
( IsDebuggerPresent() )
{
falseflagfun();
return
0;
}
else
{
GetStartupInfoA(&StartupInfo);
GetModuleFileNameA(0, Filename, 0x104u);
if
( CreateProcessA(Filename, 0, 0, 0, 0, 3u, 0, 0, &StartupInfo, &ProcessInformation) )
{
v5 = 1;
LABEL_6:
while
( v5 )
{
dwContinueStatus = 0x10002;
WaitForDebugEvent(&DebugEvent, 0xFFFFFFFF);
switch
( DebugEvent.dwDebugEventCode )
{
case
1u:
if
( DebugEvent.u.Exception.ExceptionRecord.ExceptionCode == 0x80000003 )
{
v8 = 1;
dwContinueStatus = 65538;
lpBaseAddress = DebugEvent.u.Exception.ExceptionRecord.ExceptionAddress;
ReadProcessMemory(
ProcessInformation.hProcess,
DebugEvent.u.Exception.ExceptionRecord.ExceptionAddress,
Buffer,
0x23u,
NumberOfBytesRead);
if
( NumberOfBytesRead[0] )
{
for
( i = 1; i < 35 && Buffer[i] == 0x90; ++i )
;
}
if
( i == 1 )
v8 = 0;
if
( v8 )
{
switch
( i )
{
case
4:
Context.ContextFlags = 65543;
hThread = OpenThread(0x1FFFFFu, 0, DebugEvent.dwThreadId);
if
( !GetThreadContext(hThread, &Context) )
goto
LABEL_31;
++Context.Eip;
if
( SetThreadContext(hThread, &Context) )
{
dwContinueStatus = 65538;
CloseHandle(hThread);
}
goto
LABEL_33;
case
5:
LABEL_31:
ContinueDebugEvent(DebugEvent.dwProcessId, DebugEvent.dwThreadId, 0x80010001);
goto
LABEL_6;
case
7:
WriteProcessMemory(ProcessInformation.hProcess, lpBaseAddress, v16, 7u, NumberOfBytesWritten);
if
( NumberOfBytesWritten[0] == 7 )
{
ReadProcessMemory(ProcessInformation.hProcess, lpBaseAddress, Buffer, 7u, NumberOfBytesRead);
dwContinueStatus = 65538;
}
goto
LABEL_33;
case
30:
WriteProcessMemory(ProcessInformation.hProcess, lpBaseAddress, v15, 0x1Eu, NumberOfBytesWritten);
if
( NumberOfBytesWritten[0] == 30 )
dwContinueStatus = 65538;
goto
LABEL_33;
default
:
goto
LABEL_33;
...
}
char
Main()
{
int
v1[62];
char
Str[56];
size_t
v3;
v3 = 0;
j__memset(Str, 0, 0x32u);
v1[52] = 2;
v1[53] = 3;
v1[54] = 7;
v1[55] = 14;
v1[56] = 30;
v1[57] = 57;
v1[58] = 120;
v1[59] = 251;
j__memset(v1, 0, 0xC8u);
printf
(
"Please Input Flag:\n"
);
scanf
(
"%s"
, Str);
v3 = j__strlen(Str);
__debugbreak();
printf
(
"you are too short!"
);
return
0;
}
char
Main()
{
int
v1[62];
char
Str[56];
size_t
v3;
v3 = 0;
j__memset(Str, 0, 0x32u);
v1[52] = 2;
v1[53] = 3;
v1[54] = 7;
v1[55] = 14;
v1[56] = 30;
v1[57] = 57;
v1[58] = 120;
v1[59] = 251;
j__memset(v1, 0, 0xC8u);
printf
(
"Please Input Flag:\n"
);
scanf
(
"%s"
, Str);
v3 = j__strlen(Str);
__debugbreak();
printf
(
"you are too short!"
);
return
0;
}
.text:00408AF8
int
3 ; Trap to Debugger
.text:00408AF9 nop
.text:00408AFA nop
.text:00408AFB nop
.text:00408AFC nop
.text:00408AFD nop
.text:00408AFE nop
.text:00408AFF push offset aYouAreTooShort ;
"you are too short!"
.text:00408B04 call
printf
.text:00408AF8
int
3 ; Trap to Debugger
.text:00408AF9 nop
.text:00408AFA nop
.text:00408AFB nop
.text:00408AFC nop
.text:00408AFD nop
.text:00408AFE nop
.text:00408AFF push offset aYouAreTooShort ;
"you are too short!"
.text:00408B04 call
printf
from
idaapi
import
*
from
idc
import
*
a
=
[
0x90
,
0x83
,
0x7D
,
0xF8
,
0x18
,
0x7D
,
0x11
]
b
=
0x408AF8
for
i
in
range
(
7
):
ida_bytes.patch_byte(b
+
i, a[i])
from
idaapi
import
*
from
idc
import
*
a
=
[
0x90
,
0x83
,
0x7D
,
0xF8
,
0x18
,
0x7D
,
0x11
]
b
=
0x408AF8
for
i
in
range
(
7
):
ida_bytes.patch_byte(b
+
i, a[i])
char
Main()
{
int
v1[52];
int
v2[10];
char
Str[56];
int
len;
len = 0;
j__memset(Str, 0, 0x32u);
v2[0] = 2;
v2[1] = 3;
v2[2] = 7;
v2[3] = 14;
v2[4] = 30;
v2[5] = 57;
v2[6] = 120;
v2[7] = 251;
j__memset(v1, 0, 0xC8u);
printf
(
"Please Input Flag:\n"
);
scanf
(
"%s"
, Str);
len = j__strlen(Str);
if
( len >= 24 )
{
sub_40247D(Str, v2, v1);
sub_40384B(v1);
}
printf
(
"you are too short!"
);
return
0;
}
char
Main()
{
int
v1[52];
int
v2[10];
char
Str[56];
int
len;
len = 0;
j__memset(Str, 0, 0x32u);
v2[0] = 2;
v2[1] = 3;
v2[2] = 7;
v2[3] = 14;
v2[4] = 30;
v2[5] = 57;
v2[6] = 120;
v2[7] = 251;
j__memset(v1, 0, 0xC8u);
printf
(
"Please Input Flag:\n"
);
scanf
(
"%s"
, Str);
len = j__strlen(Str);
if
( len >= 24 )
{
sub_40247D(Str, v2, v1);
sub_40384B(v1);
}
printf
(
"you are too short!"
);
return
0;
}
from
idaapi
import
*
from
idc
import
*
v15
=
[
0x90
,
0x0F
,
0xB6
,
0x55
,
0xF7
,
0x8B
,
0x45
,
0x08
,
0x8B
,
0x04
,
0x90
,
0x0F
,
0xAF
,
0x45
,
0xFC
,
0x33
,
0xD2
,
0xF7
,
0x75
,
0xF8
,
0x0F
,
0xB6
,
0x4D
,
0xF7
,
0x8B
,
0x45
,
0x0C
,
0x89
,
0x14
,
0x88
]
b
=
0xF78824
for
i
in
range
(
30
):
ida_bytes.patch_byte(b
+
i, v15[i])
from
idaapi
import
*
[培训]科锐逆向工程师培训第53期2025年7月8日开班!
最后于 2024-6-6 10:26
被Brinmon编辑
,原因: 忘记传附件了