BUUCTF之Youngter-drive~~

先运行一下程序

猜测可能是程序有反调试手段或者第三方杀毒软件误报,不管。我们继续查壳

发现有upx壳,32位PE程序,直接丢kali直接脱壳即可,然后丢ida32里面继续分析

首先在main函数中找到了几个系统线程函数。如CreateMutexW,CreateThread,CloseHandle等系统函数。

CreateMutexW:作用是找出当前系统是否已经存在指定进程的实例.

CreateThread:CreateThread是一种微软在Windows API中提供了建立新的线程的函数,该函数主线程的基础上创建一个新线程。线程终止运行后,线程对象仍然在系统中,必须通过CloseHandle函数来关闭该线程对象。

CloseHandle:关闭一个内核对象。其中包括文件、文件映射、进程、线程、安全和同步对象等。在CreateThread成功之后会返回一个hThread的handle,且内核对象的计数加1,CloseHandle之后,引用计数减1,当变为0时,系统删除内核对象。

先进入sub_4110FF函数看看

首先输出了RE,然后输入字符串进入Source所指向的空间。

然后进入第一个线程所调用的函数看看

WaitForSingleObject:WaitForSingleObject函数用来检测hHandle事件的信号状态,在某一线程中调用该函数时,线程暂时挂起,如果在挂起的dwMilliseconds毫秒内,线程所等待的对象变为有信号状态,则该函数立即返回;如果时间已经到达dwMilliseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回。

在这里就相当于,第一个线程调用该函数,然后这里的WaitForSingleObject函数用来检测之前线程的信号状态,暂时挂起

Sleep:这里的Sleep可以理解为一个延时的函数,这里是0x64,在C语言中也就是延时100毫秒,也就是延迟0.1秒,然后继续向下执行。

ReleaseMutex:释放线程的函数。

dword_418008的值为0x1D,也就是29.

这里调用了sub_41112C函数,将Source(也就是一开始输入的字符串),和dword_418008(内核对象的计数)传入了进去.

这里的意思就是如果不是大写字母或者小写字母就正常退出

如果是小写字母,则对off_418000的小写字母进行-38的加密操作

反之如果是大写字母,则对off_418000的大写字母进行-96的加密操作.

但是之前在线程中的计数是29,而这里的off_418000中的字符有52个字符。显然不对,为什么呢?

因为在第一个线程调用该函数后,会调用CloseHandle函数,内核计数就会-1,显然这里的内核计数不够。

我们继续看下个线程调用了什么函数.

可以看到第二个线程所调用的函数,并没有像第一个线程一样进行加密而是直接进行了--dword_418008,也就是直接将内核计数-1了

而在二个线程结束后,还有一个关键的函数

off_418004 = 'TOiZiZtOrYaToUwPnToBsOaOapsyS'

也就是输入的字符串经过加密后要与off_418004一一匹对即可。

梳理一下流程:

创建2个线程,内核计数初始为29.

off_418000 = 'QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm'

off_418004 = 'TOiZiZtOrYaToUwPnToBsOaOapsyS'

第一个线程对对off_418000中的大写字符和小写字符进行一个加密,但是不是每个字符都进行加密,而是对每个奇数字符进行加密,偶数字符不加密,为什么这样说呢?

第一个字符加密后(也就是数组中的a[0]),内核计数-1,然后第二个线程并没有进行任何操作了,也就是这时候内核计数再次-1了。也就是每进行一次加密,内核计数-2

而每次进行加密的时候,函数同时也会把内核计数给传入进去。

下面附上脚本:

 

posted @ 2022-12-02 15:31  Qsons  阅读(226)  评论(0编辑  收藏  举报