PETools查看exe概况
入口点:Section: [UPX1], EP: 0x00004EC0,显然有upx壳。
upx壳可直接用命令脱壳:.\upx.exe -d maze_behind_junk.exe
作者:hans774882968以及hans774882968
IDA+x64dbg识别并去除乐色代码
一载入IDA就看到我们在main函数这里。
.text:00401000 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:00401000 _main:
.text:00401000 push ebp
.text:00401001 mov ebp, esp
.text:00401003 sub esp, 18h
.text:00401006 push ebx
.text:00401007 push esi
.text:00401008 push edi
.text:00401009 push offset aGoThroughTheMa ; "Go through the maze to get the flag!\n"
.text:0040100E call sub_401140
.text:00401013 add esp, 4
.text:00401016 lea eax, [ebp-10h]
.text:00401019 push eax
.text:0040101A push offset a14s ; "%14s"
.text:0040101F call _scanf
.text:00401024 add esp, 8
.text:00401027 push eax
.text:00401028 xor eax, ecx
.text:0040102A cmp eax, ecx
.text:0040102C jnz short near ptr loc_40102E+1
.text:0040102E
.text:0040102E loc_40102E:
.text:0040102E call near ptr 0EC85D78Bh
这里有一些怪异的点:
jnz short near ptr loc_40102E+1是真的很奇怪,跳转到一个指令的中间。- IDA有一段“数据”突兀地出现在代码区。但载入x64dbg后,发现对应地址的“数据”其实是代码。
这只能说明一件事:IDA没能识别许多代码。而原因就在于:0EC85D78Bh本身其实是一条汇编指令,而IDA被call near ptr对应的1字节数据干扰了。
解决:使用Edit -> Patch program -> Change byte,把0x40102e处的E8改成90(对应nop)即可。
这一操作之后,IDA能够识别那些数据了。但还不能F5。于是我们手工创建函数:在函数的第一个字节所对应的行,右键,Create function。这样就能F5了。
sub_401140就是printf。
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4; // [sp+0h] [bp-24h]@0
int v5; // [sp+0h] [bp-24h]@1
signed int i; // [sp+10h] [bp-14h]@1
char v7[16]; // [sp+14h] [bp-10h]@1
sub_401140((int)aGoThroughTheMa, v4);
scanf(a14s, v7);
for ( i = 0; i <= 13; ++i )
{
switch ( v7[i] )
{
case 'w':
++dword_40807C;
break;
case 's':
--dword_40807C;
break;
case 'a':
--dword_408078;
break;
case 'd':
++dword_408078;
break;
default:
continue;
}
}
if ( dword_408078 != 5 || dword_40807C != -4 )
{
sub_401140((int)aTryAgain___, v5);
}
else
{
sub_401140((int)aCongratulation, v5);
sub_401140((int)aHereIsTheFlagF, (int)v7);
}
return 0;
}
/*
dword_408078 dd 7
dword_40807C dd 0
*/
找迷宫地图
题目名《Maze》但这段代码没有用到“迷宫”?于是我运行了程序,输入aaddaasswwssss、adaadaswssssws发现它们都被认为是flag。
这说明迷宫得自己找,直接在IDA打开Strings window即可找到迷宫字符串,shift+E导出,长度为70。
*******+********* ****** **** ******* **F****** **************
行和列怎么求?其实凭直觉我们也很容易求出,但这里想用更加数学的方法。
约定:x,y分别表示行、列索引,0-indexed。
namoid = c*x+y。又根据以上代码和“单机游戏常识”,s键使得行增加,a使得列减少。所以我们不难得出终点(5,-4)的-4表示行坐标。于是有以下代码:
def main():
maze = "*******+********* ****** **** ******* **F****** **************"
sid = maze.index("+")
eid = maze.index("F")
ex,ey = -4,5
c = (eid - ey) // (-ex)
r = len(maze) // c
print(r,c)
for i in range(r):
print(maze[c*i:c*(i+1)])
if __name__ == "__main__":
main()
迷宫如下:
*******+**
******* **
**** **
** *****
** **F****
** ****
**********
flag{ssaaasaassdddw}