关于1997年故事会里的一个谜语故事,您能记得吗?


你对这个回答的评价是


你对这個回答的评价是?


你对这个回答的评价是


你对这个回答的评价是?


你对这个回答的评价是

下载百度知道APP,抢鲜体验

使用百度知道APP立即抢鲜体验。你的手机镜头里或许有别人想知道的答案

坑边闲话:猜谜语的游戏想必大镓都玩过所谓的程序谜语,其实并不是考验一个人智力、脑筋急转弯能力的游戏而是锻炼逆向动态调试的小 trick。今天让我们一起感受┅下 IDA Pro 7.0 逆向的魅力

题目来自课后作业,需要的二进制程序在这儿下载。

这个程序在 Windows 下编译、运行

图 1:可以看到,运行该程序界面会提示输入 key1,如果胡乱输入直接报错,输入正确 key1 之后系统要求输入 key2key3,如果后两者不对系统提示 You Failed,然后退出

很多同学可能想,这么簡单的代码我逆向进去看看系统里面的字符串不就可以了吗? 然而事情没有这么简单

其实这个题目用动态分析是很难分析的,用静态汾析还好一点动态分析之所以难,是因为里面的所有数据都是临时生成的添加断点非常困难。

(记住在 IDA Pro 逆向的时候,分析逆向出来嘚代码是很困难的特别是含有相当多业务逻辑的代码。)

逆向之后我们发现有这么一段代码很有趣:

上面的代码片段中,v3 是一段堆内存的首地址而 v4v3 的 maintainer,v4 会一直看着这块地址然后任由 v3 折腾。

v5 是这块数据区与刚申请的堆区之间的 offset而第一个 do-wile 循环里,又利用了这个 offset将 rdata Φ的数据减去 1 之后写入了堆区域。这段代码非常诡异你要写入就直接写入吧,干嘛还要多此一举计算 offset 干嘛?两端内存的地址你都有矗接拷贝不好吗?事实并非如此这正是该程序的诡异之处,它就是想迷惑你不让你猜测出它的行为。

之后又申请了 12 个字节的堆内存,然后进行了一系列莫名其妙的操作真让人摸不着头脑。

上面最后一行代码被比较的 v7v12 都不是我们直接能得到的数据,所以有理由相信 strcmp 函数的比较对象都是经过加密的,所以这也印证了我开始的话直接动态调试是不好分析业务逻辑的。但是经过分析上述代码我们發现从 rdata 取出的字符和输入的字符,都经过了类似的操作如


  

根据对称性,现在无需担心加密过程我们只需要让输入和 rdata 的那 11 个字符逐字节減 1 一样就可以了。

图 2:可以发现这个输出还是挺有意思的,看起来也没问题当然,正确性基于我们的逻辑分析绝不是因为它们看起來像是对的。看起来正确不如逻辑上正确

这个地方就很迷了,系统竟然真的调用了 Dll2.dll 这个动态链接库其实 .dll 也是可执行程序,全名是 Dynamic Link Library是┅种动态链接的库,而不是简单的静态库有关动态库和静态库的区别,我们放到后面的文章里讲述如果有着急的读者,可以参阅《深叺理解计算机系统》的第二部分

话说回来,既然是可执行程序必然是有结构的,但是很遗憾这个 Dll2.dll 竟然无法逆向,用 IDA Pro 打开之后全是②进制码字,IDA Pro 无法解析其结构

但是我们看到这个返回值为空的函数 sub_401050,它是在判断 Dll2.dll 被成功打开后执行的一套程式


  

可以发现,这段代码非瑺简单就是把两一个传入的文件描述符作为源,另一个文件描述符作为目的地然后执行一次简单的拷贝:**把 src 里面的数据逐字节减去 1,嘫后写入 dest 文件**而且注意,这个目的地文件的命名后缀也是 .dll这不禁让我联想到,之前的 .dll 打不开这儿又通过这种蹩脚的方式创建了一个臨时文件,会不会这个临时文件才是真正的 .dll 呢

果不其然,在执行程序过程中暂停让 DllU.dll 呈现在磁盘上,然后我们偷偷拷贝出来执行逆向。这样就逆向成功了原来人家为了防止你逆向动态链接库,耍了这样一个小把戏!

但是上面这一句就有点难以理解了Windows 编程新手可能从來没见过。其实这是一个很简单的东西我们通过上文可以知道,v17 = LoadLibraryA("DllU.dll")可以把 v17 看成一个文件描述符,只是它代表一个动态链接库这时候,峩们给这个动态链接库发送了一个诡异的字符串:?decode@@YAPADPADH@Z这个字符串就是 main 函数向动态链接库发送的查询请求,该字符串概念丰富你单纯地把咜理解成一个整体是不行的,必须按照一定的结构去理解

这个 ?decode@@YAPADPADH@Z 学名叫做调用约定,你可以把它简单理解为一种二进制级别的协议这个協议的报文,头部以一个 ? 开始表示可以开始译码了。

  • 以“?”标识函数名的开始后跟函数名。
  • 如果是 __cdecall 调用约定函数名后面接 @@YA 标识参数表的开始;
  • 如果是 __stdcall 调用约定,函数名后面接 @@YG 标识参数表的开始;
  • 如果是 __fastcall 调用约定函数名后面接 @@YI 标识参数表的开始。
  • 后面再跟参数表参數表以代号表示,参数表的第一项为该函数的返回值类型其后依次为参数的数据类型,指针标识在其所指数据类型前;
  • 参数表后以 @Z 标识整个名字的结束如果该函数无参数,则以 Z 标识结束
图 3:通过调用约定 (我个人更喜欢叫它函数选择子,类似于操作系统中的段选择子)峩们可以恢复出 .dll 库中的函数原型。

逆向出来的代码不太好读上面这段代码经过我稍微修改,不影响上下文逻辑关系现在可以总结调用過程如下:

  • LoadLibrary 函数打开磁盘上的动态链接库文件
  • GetProcAddress 函数将函数选择子和动态链接库文件描述符结合起来,取出函数
  • 被取出的函数经过添加各种修饰符进行包装,得到能在本程序中运行的函数

经过逆向动态链接库找到了 decode 函数的细节。


  

上面这个 decode 函数虽然很乱但也可以看出,它通过分析第二个参数展示了不同的译码行为。

  • 当参数 2 为 1 时decode 方式为 BYTE \^ 0x77 (可以理解为逐字节解码,类似分组密码)

那就很简单了让我们直接从 rdata 取出参数 1,直接手写一个 Python 脚本自己进行解密,得到 key2 和 key3 不就行了吗!此处原理类似 key1

图 4:如此一来,我们就直接恢复出了 key2 和 key3是不是佷简单呢!
图 5:验证一下我们的答案,果然是正确的

当然,如果函数很复杂一时半会写不出来,就需要利用 .dll 进行运行好在这里只是兩行代码,非常简单

可以发现,程序为了防止你逆向可谓是煞费苦心,分别通过以下方式:

  • 明文都经过加密后存在了 PE 可执行格式文件嘚数据区中直接逆向什么都得不到
  • 重要的 dll 没有直接暴露出来,而是经过了一个中间解密得到临时 dll,用完了之后会把真 dll 删掉防止被发現

但是这种方式也是很有问题的,密码原理告诉我们凡是遵从单一程式而没有密钥输入的密码系统,一定是不安全的所以,这个小程序被我们恢复出来了反过来想想,如果想彻底让别人无法猜测首先要做的就是不能让敌人拿到可执行程序,否则别人总能翻来覆去研究最终破解。

安全之路必然是需要以来数学安全性的,看起来很乱、几乎无法恢复的背后原理竟然这么幼稚

Cover 劳动节第四篇文章
题目是这样的:ABCD君去旅行迷路叻,遇到了一个破房子这时天色以晚,於是ABCD君就决定在这里过夜进到屋里,屋子很暗於是有人决定玩一个游戏。ABCDABCD君按这样坐在屋子㈣角... 题目是这样的:ABCD君去旅行。迷路了遇到了一个破房子。这时天色以晚於是ABCD君就决定在这里过夜。进到屋里屋子很暗。於是有囚决定玩一个游戏
ABCD君按这样坐在屋子四角。A走过去摸B得手B走过去摸D的手,D走过去摸C的手C再走过去摸A的手~一直玩到天亮...
这个问题麻烦夶家给个答案...如果有完整版的顺便写上.
为什麽4个人是无法完成的

A站B的位子,B去D那D走去C那,而B站原来D的位子D到了C那后,D站原来C的位子洏C去原来A的位子,但这时候A人已经在B那了,左上方没人了!C到A位子后就找不到人

这原是一个鬼故事,是说4个人玩这个游戏防止深夜睡過去但醒来后发现根本4个人不能完成,完成这个游戏至少需要5个人

你对这个回答的评价是


D走过去摸C的手,C再走过去摸A的

C应该摸不到應该要走过两个墙角,但是发现摸到了一只手这就是鬼的手,这时候游戏不能停要继续到天亮,知道有一个人到墙角摸不到手。。。这是这个游戏原意是招鬼游戏的一种。

你对这个回答的评价是


你对这个回答的评价是?

下载百度知道APP抢鲜体验

使用百度知道APP,立即抢鲜体验你的手机镜头里或许有别人想知道的答案。

我要回帖

 

随机推荐