BUUCTF逆向题Youngter-drive-CSDN博客
逆向每日一题----Youngter-drive题解-CSDN博客
借鉴博客,写得比我好
upx拖壳
upx -d Youngter-drive.exe
这道题我不知道为什么,我这里是运行不了的,也没有找到原因
int __cdecl main_0(int argc, const char **argv, const char **envp)
{
HANDLE Thread; // [esp+D0h] [ebp-14h]
HANDLE hObject; // [esp+DCh] [ebp-8h]
sub_DA10FF();
::hObject = CreateMutexW(0, 0, 0);
j_strcpy(Destination, &Source);
hObject = CreateThread(0, 0, StartAddress, 0, 0, 0);
Thread = CreateThread(0, 0, sub_DA119F, 0, 0, 0);
CloseHandle(hObject);
CloseHandle(Thread);
while ( dword_DA8008 != -1 )
;
sub_DA1190();
CloseHandle(::hObject);
return 0;
}
这是第一个sub函数
36位的flag
这段代码是使用C语言风格的Windows API函数来创建互斥体(Mutex)、线程以及关闭句柄的操作。下面是对每行代码的详细解释:
::hObject = CreateMutexW(0, 0, 0);
- 这行代码在全局命名空间中创建一个互斥体(Mutex)。
CreateMutexW
是Windows API中的一个函数,用于创建一个内核对象,用于同步多个线程对共享资源的访问,确保同一时间只有一个线程可以访问资源。- 参数说明:
- 第一个参数为
LPSECURITY_ATTRIBUTES lpMutexAttributes
,指定了互斥体的安全属性,默认设为0
,表示使用默认安全属性。- 第二个参数为
BOOL bInitialOwner
,指定创建线程是否立即拥有该互斥体。设为0
意味着调用者不立即拥有互斥体。- 第三个参数为
LPCWSTR lpName
,为互斥体指定一个名称,这里也是0
,表示创建一个未命名的本地互斥体。::hObject
是一个全局或静态变量,用于存储新创建的互斥体的句柄。
j_strcpy(Destination, &Source);
- 这行代码似乎是用来复制字符串的,但
j_strcpy
并不是标准库中的函数,可能是自定义的或特定库中的函数,其作用类似于strcpy
,将Source
指向的字符串复制到Destination
指向的缓冲区中。
hObject = CreateThread(0, 0, StartAddress, 0, 0, 0);
- 创建一个新的线程。
CreateThread
是Windows API中的函数,用于创建一个新的线程并执行指定的函数。- 参数说明:
- 第一个参数为
LPSECURITY_ATTRIBUTES lpThreadAttributes
,同上,指定线程的安全属性,这里为0
,使用默认设置。- 第二个参数为
SIZE_T dwStackSize
,指定线程栈的大小,设为0
表示使用系统默认大小。- 第三个参数为
LPTHREAD_START_ROUTINE lpStartAddress
,是指向线程开始执行的函数地址,这里是StartAddress
。- 第四个参数为
LPVOID lpParameter
,传递给线程函数的参数,这里为0
,没有传递参数。- 第五个参数为
DWORD dwCreationFlags
,控制线程创建的标志,设为0
表示无特殊标志。- 第六个参数为
LPDWORD lpThreadId
,输出参数,返回新线程的ID,这里没有使用,所以传入了0
。hObject
被重新赋值为新创建线程的句柄。
Thread = CreateThread(0, 0, sub_DA119F, 0, 0, 0);
- 同样是创建一个线程,但这次执行的函数是
sub_DA119F
。Thread
变量用于存储这个新线程的句柄。
CloseHandle(hObject);
- 关闭之前创建的互斥体或线程的句柄。
CloseHandle
是Windows API中的函数,用于释放与句柄关联的系统资源。这里关闭的是第一个线程的句柄(尽管变量名是hObject
,但根据上下文应该是线程句柄)。
CloseHandle(Thread);
- 关闭第二个线程的句柄,释放与之关联的系统资源。
总结来说,这段代码首先创建了一个互斥体,然后创建了两个线程,每个线程都去执行不同的函数(
StartAddress
和sub_DA119F
),最后关闭了这两个线程的句柄以及(可能误标为)互斥体的句柄。注意,互斥体创建后并未显示地在代码中使用,也没有进行线程间的同步操作,这可能是个疏忽或者示例代码片段的一部分。此外,字符串复制操作与线程创建看起来是独立的操作,没有直接关联。
我理解下,就是有两个进程,一个进程进行一个函数
第一个线程h0bject会执行StartAddress函数,第二个线程v2执行sub_41119f函数,
首先找到我们已知的加密吧,这是第一个,可以看见flag是由destination来的
destination是source来的
挨个跟进source
如果是大写,-38
如果是小写 -96
至于上没那个报错,我们可以看见,这里的堆栈变成-04了,明显是错误的
1、代码插入了花指令,但是这种会导致无法使用F5进行反编译,所以针对本题而言,不是花指令导致的不平衡
2、代码函数出现了分离,就是一段代码被拆分为两部分,所以在进行恢复现场的时候,通常是使用了jmp的强制跳转,然后被硬生生分成了两部分
3、还有可能是定义的调用约定与使用的不同,因为不同的调用约定进行清理堆栈的操作不同,那stdcall与cdecl两种对比:
对于stdcall:
由调用的函数自己进行清理使用的堆栈
对于cdecl:
他的清理堆栈是由调用者自己进行回复堆栈,()
总结一下思路
!这里因为每一个线程里面有sleep函数,这里程序会先执行下一个同等线程,所以是先第一个进程,然后第二个,然后回到一个~!!!!!!我giao,学到了<但是第二个线程没什么加密
然后这里进行了30次
但是我得到的密文只有29位
应该有一个是我们需要爆破的
因为是交替的,所以有个问题!这里dowrd是公用了,那么第一个加密后,第二个就不会加密了!
所以只加密15个
flag1 = 'QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm'
d = 'TOiZiZtOrYaToUwPnToBsOaOapsyS'
flag="flag{"
for i in range(len(d)):
if i%2 == 0:
flag+=d[i]
else:
if(d[i].isupper()):
flag+=chr(flag1.find(d[i])+96)
else:
flag+=chr(flag1.find(d[i])+38)
flag+="}"
print(flag)
____________________
flag{ThisisthreadofwindowshahaIsES}
这段长度只有35个,错误
你还记得吗?开头我们看见了sancf的参数是36,说明还有一个我们没有找到
最后加个E(w sou d )
最后我说一下我对于这个堆栈的题的理解
其实这道题有些人可以发现,我们不改esp也可以通过
[求助]IDA为什么产生 sp-analysis failed-软件逆向-看雪-安全社区|安全招聘|kanxue.com
看着里面的一位大神的评论
你再看这里
不是一模一样?