本人是新手,如果有不对,请各位师傅帮忙指明,共同进步(感谢!!!)
附上题目地址:
https://buuoj.cn/challenges
首先,查壳,然后脱壳分析,然后找到main函数进行分析
main函数有几个特殊的函数,搜素一下其含义:(下面是借鉴的下面大佬的blog,学习一波ORZ)
函数学习:
createMutexW 函数 创建或打开命名或未命名的互斥对象。 HANDLE CreateMutexW( [in, optional] LPSECURITY_ATTRIBUTES lpMutexAttributes, [in] BOOL bInitialOwner, [in, optional] LPCWSTR lpName ); 特性: a.独占性-在某个时间点上,只有一个线程拥有互斥,别的线程等待,除非这个线程扔掉后,别的线程才会拥有互斥 b.所有线程都没有互斥时,线程句柄有信号,如果有一个线程拥有互斥,线程句柄无信号 CreateThread函数 创建一个在调用进程的虚拟地址空间内执行的线程。 HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, __drv_aliasesMem LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId ); WaitForSingleObject 函数 WaitForSingleObject是一种Windows API函数。当等待仍在挂起状态时,句柄被关闭,那么函数行为是未定义的。该句柄必须具有 SYNCHRONIZE 访问权限。 CloseHandle 函数 关闭一个内核对象。其中包括文件、文件映射、进程、线程、安全和同步对象等。在CreateThread成功之后会返回一个hThread的handle,且内核对象的计数加1,CloseHandle之后,引用计数减1,当变为0时,系统删除内核对象。 原文链接:https://blog.csdn.net/m0_73644864/article/details/128848145
所以这个两个函数是创建两个进程,然后交替进行操作,实现两次加密
但是点开其中一个,他是没有加密的,只有一个有加密。
第一次加密:
首先看到sub_4110FF()双击查看是进行了什么操作:
可以发现是进行了输入操作,此时的source就是flag
点击 X 进行交叉引用查看有什么进行了改变
发现有不少处进行了引用,依次点击进行查看进行了什么操作
此处应该是进行了比较,然后就是输出flag,所以密文在此处
查看第二处调用source的地方,此处就是上面锁对应的第二个加密的地方
第二次加密:
堆栈不平衡
此处有一个爆红,栈帧不平衡。
我搜索了相关的问题,得到出现这种问题通常有三种情况
1、代码插入了花指令,但是这种会导致无法使用F5进行反编译,所以针对本题而言,不是花指令导致的不平衡
2、代码函数出现了分离,就是一段代码被拆分为两部分,所以在进行恢复现场的时候,通常是使用了jmp的强制跳转,然后被硬生生分成了两部分
3、还有可能是定义的调用约定与使用的不同,因为不同的调用约定进行清理堆栈的操作不同,那stdcall与cdecl两种对比:
对于stdcall: 由调用的函数自己进行清理使用的堆栈,可以看到函数最后的返回会出现ret 8 类似的 对于cdecl: 他的清理堆栈是由我们调用者自己进行回复堆栈,在 call function() add esp 8
回到正题,我们可以看到在这个函数里有一个jmp,所以可能是因为第二种条件造成的堆栈不平衡
下面提供解决方法:
1、使用 ALT + K 进行处理,指定栈帧更改的字节数,目的要使得ret最后的ESP为0
再对上面进行恢复
f5一下可以看到,已经不出现爆红了
观察代码,可以发现这就是加密代码了
x='QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm'
y='TOiZiZtOrYaToUwPnToBsOaOapsyS'
flag=''
for i in range(len(y)):
if i%2==0:
flag+=y[i]
else:
if(y[i].isupper()):
flag+=chr(x.find(y[i])+96)
else:
flag+=chr(x.find(y[i])+38)
print(flag)
但是最后的答案不对?,查了要多加一个E
flag就是:、
flag{ThisisthreadofwindowshahaIsESE}
以上是我的简介,如有错误,请各位师傅指正。