BUU Youngter-drive wp

Youngter-drive

拿到题目,发现有upx壳,先去壳,然后丢入IDA 分析
BUU Youngter-drive wp_第1张图片
看到这里我们应该先了解一下关于Windows多线程的知识

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

可以看出主函数中创建了2个子线程,我们分别进行分析
StartAddress:
BUU Youngter-drive wp_第2张图片
这里我们回到main函数中打开sub_411190()函数可以找到Source的的赋值
BUU Youngter-drive wp_第3张图片
在这里插入图片描述

sub_41119F:
BUU Youngter-drive wp_第4张图片

WaitForSingleObject
WaitForSingleObject是一种Windows API函数,当等待仍在挂起状态时,句柄被关闭,那么函数行为是未定义的。该句柄必须具有 SYNCHRONIZE 访问权限。
WaitForSingleObject函数用来检测hHandle事件的信号状态,在某一线程中调用该函数时,线程暂时挂起,如果在挂起的dwMilliseconds毫秒内,线程所等待的对象变为有信号状态,则该函数立即返回;如果超时时间已经到达dwMilliseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回。
ReleaseMutex
ReleaseMutex是一种线性指令,具有释放线程拥有的互斥体的控制权。

线程也能告诉系统,它不想在某个时间段内被调度。
这是通过调用Sleep函数来实现的:
VOID Sleep(DWORD dwMilliseconds);
该函数可使线程暂停自己的运行,直到dwMilliseconds过去为止。

因此这两个线程是交替进行的,现在我们对第一个线程进行分析:
BUU Youngter-drive wp_第5张图片
(这里如果用IDA7.5可以不用平衡堆栈就可以F5,用别的版本可能需要平衡堆栈)

dword_418008(也就是a2)的初始值是0x1D,也就是倒序遍历字符串,逆向逻辑也很简单,简单分析一下即可。

然后我们再看一下第二个线程发现除了 - -dword_418008 什么也没干。

这样就好办了,就是在dword_418008为奇数时,进行线程1,偶数时进行线程2,直到dword_418008=-1

整理好思路后写出脚本

#include
using namespace std;
char flag[100]="TOiZiZtOrYaToUwPnToBsOaOapsyS";
string key="QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm";
int main()
{
	for(int i=28;i>=0;i--)
	{
		if(i%2==0) continue;
		for(int j=0;j<key.length();j++)
			if(key[j]==flag[i])
			{
				if(flag[i]>=65&&flag[i]<=90) 
				{
					flag[i]=j+96;
					break;
				}
				else
				{
					flag[i]=j+38;
					break;
				}
			}
	}
	for(int i=0;i<=28;i++) cout<<(char)flag[i];
	return 0;
}

得到flag:ThisisthreadofwindowshahaIsES

但是交上去发现不对,重新看了一下比较函数发现虽然flag有30位,但是只比较了29位,一个一个字母试一试,发现最后一个字符为“E”。

flag{ThisisthreadofwindowshahaIsESE}

你可能感兴趣的:(RE)