反编译源码:
条件判断:
第一个判断是输入的flag的最后一个字符的地址-v11的起始地址是否等于26,应该就是需要flag的长度为26:
后面两个判断就是判断flag的格式为:ACTF{xxxx}
strtok,用_
将字符串分隔开,v3取的是最左边的一段字符,ACTF{xxxx
,注意v17是从第六个字符开始,取4个字符的长度,然后v18是从第10个字符开始,取两个字符,这样其实都可以推断出来整个flag的格式为ACTF{xxxxxx_xxxxxx_xxxxxx}
往下存在一个unk_4051D8
:
发现把unk_4051D8
当成函数执行:((int (__cdecl *)(int *))unk_4051D8)(&v17)
,说明上面的一大段数据应该是字节码,然后将v17当成参数传入该函数中,重新运行,输入ACTF{aaaaaa_bbbbbb_cccccc}
,用x32dbg动态跟:
第一个循环:
异或结果:
看到EIP,发现就是通过循环解密出后面需要执行的字节码:
解密之后的push ebp才是真正的函数开始,该函数先是往内存写值,一个是3@1b;b
,一个是Welcome
:
往下对刚刚写入的字符串的进行循环异或,
6次循环后得到:yOu0y*
最后出循环,test eax, eax,说明eax是作为函数执行结果,
重新运行执行输入:
ACTF{abcdef_hijklm_opqrst}
处理完第一个strtok之后会得到一个字符串为:abcdefRvabcdef
,中间的Rv是固定的
三次strtok处理完之后会得到这样的结果:
然后来到字节码部分,注意传进来的字符串为:abcdefRvabcdef
进来之后先对字节码进行解密,解谜之后从0x9F515C开始才是函数处理的开始,注意传入的参数由EDX指向:
随后生成3@1b;b
和welcome
,对这两个值进行异或再加上0x23,然后跟传入的字符串进行对比,不难发现预期值应该是两个相等的,往下走完循环拿完处理后的结果为yOu0y*
重新运行:
此时相等了,跳转不实现:
将edx作为计数器来存储相等的个数,最后对比是否全部相等,将返回值置为1:
往下来到第二个部分的验证:
异或之后的值作为key,然后对:405018开始的值进行异或,跟第一个函数一样,通过这个key对字节码进行解密,然后再执行,这里的内容就是第二部分字符串的验证:
开局几个循环啥事都没干就是将输入的第二部分字符串进行memcpy,到这个位置才真正对字符串进行处理:
往下的mov很重要,EAX此时的值为0x705018,也就是该函数的字节码首地址,这里异或的结果作为数组下标,将字节码以byte的形式存储到EBX:
往下从0x705018+0x166取值与上面通过偏移拿到的值进行比较:
edi作为计数器,回到异或之前可以看到ecx的值来自于edi:
得到异或逻辑为:
exp:
byte_405018,用Ghidra的字节复制复制下来:
得到flag2:
第三部分字符串发现就是直接进行strncmp:
可以得到第三部分的字符串为:5mcsM<
,最终flag:
int
__cdecl main(
int
argc, const char
*
*
argv, const char
*
*
envp)
{
char
*
v3;
/
/
eax
char
*
v4;
/
/
eax
char v6;
/
/
[esp
+
0h
] [ebp
-
68h
]
int
i;
/
/
[esp
+
14h
] [ebp
-
54h
]
char
*
v8;
/
/
[esp
+
18h
] [ebp
-
50h
]
char v9;
/
/
[esp
+
20h
] [ebp
-
48h
]
char flag[
25
];
/
/
[esp
+
24h
] [ebp
-
44h
] BYREF
char v11[
25
];
/
/
[esp
+
25h
] [ebp
-
43h
] BYREF
char v12;
/
/
[esp
+
3Dh
] [ebp
-
2Bh
]
int
v13;
/
/
[esp
+
44h
] [ebp
-
24h
]
__int16 v14;
/
/
[esp
+
48h
] [ebp
-
20h
]
char v15[
4
];
/
/
[esp
+
4Ch
] [ebp
-
1Ch
]
__int16 v16;
/
/
[esp
+
50h
] [ebp
-
18h
]
int
v17;
/
/
[esp
+
54h
] [ebp
-
14h
] BYREF
__int16 v18;
/
/
[esp
+
58h
] [ebp
-
10h
]
int
v19;
/
/
[esp
+
5Ch
] [ebp
-
Ch]
__int16 v20;
/
/
[esp
+
60h
] [ebp
-
8h
]
sub_401020(
"%s\n"
, (char)aWelcomeToActfS);
sub_401050(
"%s"
, (char)flag);
if
( &flag[strlen(flag)
+
1
]
-
v11
=
=
26
&& !strncmp(flag,
"ACTF{"
,
5u
) && v12
=
=
'}'
)
{
v12
=
0
;
v3
=
strtok(flag,
"_"
);
v17
=
*
(_DWORD
*
)(v3
+
5
);
v18
=
*
(_WORD
*
)(v3
+
9
);
v19
=
*
(_DWORD
*
)(v3
+
5
);
v20
=
*
(_WORD
*
)(v3
+
9
);
v4
=
strtok(
0
,
"_"
);
v13
=
*
(_DWORD
*
)v4;
v14
=
*
((_WORD
*
)v4
+
2
);
v8
=
strtok(
0
,
"_"
);
*
(_DWORD
*
)v15
=
*
(_DWORD
*
)v8;
v16
=
*
((_WORD
*
)v8
+
2
);
dword_403354
=
(
int
)&unk_4051D8;
if
( ((
int
(__cdecl
*
)(
int
*
))unk_4051D8)(&v17) )
{
v9
=
BYTE2(v19) ^ HIBYTE(v20) ^ v19 ^ HIBYTE(v19) ^ BYTE1(v19) ^ v20;
for
( i
=
256
; i <
496
;
+
+
i )
byte_405018[i] ^
=
v9;
__asm { jmp eax }
}
}
sub_401020(
"Wrong\n"
, v6);
return
0
;
}
int
__cdecl main(
int
argc, const char
*
*
argv, const char
*
*
envp)
{
char
*
v3;
/
/
eax
char
*
v4;
/
/
eax
char v6;
/
/
[esp
+
0h
] [ebp
-
68h
]
int
i;
/
/
[esp
+
14h
] [ebp
-
54h
]
char
*
v8;
/
/
[esp
+
18h
] [ebp
-
50h
]
char v9;
/
/
[esp
+
20h
] [ebp
-
48h
]
char flag[
25
];
/
/
[esp
+
24h
] [ebp
-
44h
] BYREF
char v11[
25
];
/
/
[esp
+
25h
] [ebp
-
43h
] BYREF
char v12;
/
/
[esp
+
3Dh
] [ebp
-
2Bh
]
int
v13;
/
/
[esp
+
44h
] [ebp
-
24h
]
__int16 v14;
/
/
[esp
+
48h
] [ebp
-
20h
]
char v15[
4
];
/
/
[esp
+
4Ch
] [ebp
-
1Ch
]
__int16 v16;
/
/
[esp
+
50h
] [ebp
-
18h
]
int
v17;
/
/
[esp
+
54h
] [ebp
-
14h
] BYREF
__int16 v18;
/
/
[esp
+
58h
] [ebp
-
10h
]
int
v19;
/
/
[esp
+
5Ch
] [ebp
-
Ch]
__int16 v20;
/
/
[esp
+
60h
] [ebp
-
8h
]
sub_401020(
"%s\n"
, (char)aWelcomeToActfS);
sub_401050(
"%s"
, (char)flag);
if
( &flag[strlen(flag)
+
1
]
-
v11
=
=
26
&& !strncmp(flag,
"ACTF{"
,
5u
) && v12
=
=
'}'
)
{
v12
=
0
;
v3
=
strtok(flag,
"_"
);
v17
=
*
(_DWORD
*
)(v3
+
5
);
v18
=
*
(_WORD
*
)(v3
+
9
);
v19
=
*
(_DWORD
*
)(v3
+
5
);
v20
=
*
(_WORD
*
)(v3
+
9
);
v4
=
strtok(
0
,
"_"
);
v13
=
*
(_DWORD
*
)v4;
v14
=
*
((_WORD
*
)v4
+
2
);
v8
=
strtok(
0
,
"_"
);
*
(_DWORD
*
)v15
=
*
(_DWORD
*
)v8;
v16
=
*
((_WORD
*
)v8
+
2
);
dword_403354
=
(
int
)&unk_4051D8;
if
( ((
int
(__cdecl
*
)(
int
*
))unk_4051D8)(&v17) )
{
v9
=
BYTE2(v19) ^ HIBYTE(v20) ^ v19 ^ HIBYTE(v19) ^ BYTE1(v19) ^ v20;
for
( i
=
256
; i <
496
;
+
+
i )
byte_405018[i] ^
=
v9;
__asm { jmp eax }
}
}
sub_401020(
"Wrong\n"
, v6);
return
0
;
}
&flag[strlen(flag)
+
1
]
-
v11
=
=
26
&& !strncmp(flag,
"ACTF{"
,
5u
) && v12
=
=
'}'
&flag[strlen(flag)
+
1
]
-
v11
=
=
26
&& !strncmp(flag,
"ACTF{"
,
5u
) && v12
=
=
'}'
cyclic
26
-
> flag{aaaabaaacaaadaaaeaaa}
cyclic
26
-
> flag{aaaabaaacaaadaaaeaaa}
v3
=
strtok(flag,
"_"
);
v17
=
*
(_DWORD
*
)(v3
+
5
);
v18
=
*
(_WORD
*
)(v3
+
9
);
v19
=
*
(_DWORD
*
)(v3
+
5
);
v20
=
*
(_WORD
*
)(v3
+
9
);
v4
=
strtok(
0
,
"_"
);
v13
=
*
(_DWORD
*
)v4;
v14
=
*
((_WORD
*
)v4
+
2
);
v8
=
strtok(
0
,
"_"
);
*
(_DWORD
*
)v15
=
*
(_DWORD
*
)v8;
v16
=
*
((_WORD
*
)v8
+
2
);
v3
=
strtok(flag,
"_"
);
v17
=
*
(_DWORD
*
)(v3
+
5
);
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2022-3-13 00:12
被Gushang编辑
,原因: 添加附件