旧文迁移,将自己带入二进制大门的一道逆向题与书上的第一道逆向实例~
第一题
的第一道逆向题,贼激动,现在来记一下,这是ZJGSCTF逆向第一道,需要在Win7及以上系统运行(由于存在ASLR,加载基址可能会随机变化,所以以下地址可能每次不同,按顺序来就好了):
打开od找关键词:
双击进入:
这里Input Your Flag:这个字符串后有三个调用,猜测下:
第一个调用应该类似printf函数,参数为字符串首地址。
第二个调用类似scanf函数,输入的值保存在ebp-0x38这个地址处
第三个调用有三个参数,用到了第二个调用使用的参数,那里保存着字符串,那么猜测这是一个字符串拷贝函数,将ebp-0x38处字符串拷贝到ebp-0x134位置,最大拷贝0x32个字节。运行程序到此处进行验证:
在第一个调用处输出,并在第二个调用处阻塞了,输入一个很长的字符串试试:
0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef(共40H字节)
运行后,发现ebp-0x134处(堆栈窗口默认跟踪指示的是ESP指向的位置,可以使用Ctrl+G迅速跳转到其他位置)存的是” 0123456789abcdef0123456789abcdef0123456789abcdef01S”这个字符串,是输入值被截断到32H长度后的值, 即定义ebp-0x134为新串,ebp-0x38为原串,那么原串和新串唯一的不同在于一个新串是源串的前32H字节。接着向下走,:
1 | MOVZX AX,80H ;对80H进行无符号扩展后赋值给AX,即在AX中值为0080H |
如图,这里对新串进行了一些交换和加法运算,在交换位置过程中,并没有使用临时变量,而是充分利用了原始字符串,这里就不写具体算法了。。。
继续,执行,会执行到一个莫名其妙的区域,的确可以执行,还以为是没有学过的汇编指令,于是直接跳过这个区域,但是却发现新串又被改变了,即说明这个区域又对新串进行了运算(加密)
于是,经过几次尝试,发现明文和密文存在某种恒定的对应关系,然后自己神奇使用0-9a-zA-Z及所有可能的其他符号枚举了它的加密后对应关系。。。不过,这里其实用了代码未对齐干扰调试,去掉分析功能即可:
看到这里就是一些异或运算:
继续运行:
终于进入正题,在这里看到了答案错误出现的Error!它来自上面不远处的跳转,说明那里就是判断输入是否正确的地方,这里是一个循环,将输入、处理后的字符串与内存中存在的正确的加密后的字符串进行比较,要是不一样就跳转,直到比较完成,注意到这里其实只比较了19次(0~48H,步长为4),最后证明还有一个字符需要自己猜。。。好了,完成。。。
第二题
哈哈,终于不是我一个人记了,闺蜜ESE也加入了,开森!
运行程序
收集到的字符串,如图
然而并没有什么用,应该是都加密了,搜不到
而这道题就是要求修改上面两个框里的字符串内容。
调试
还是先把节区信息放在这里:
前面几个函数后面直接就是ret,说明肯定是要跟入的,进入后走着,看见这里有个惹眼的xor,eax的值为10F5,此处(4010F5及以后154H字节)的值与44H异或
接着下面两个函数后就结束了,那这两个至少有一个必须要跟入,先进入第一个:
这又是两个解码循环,第一个是401007H及以后7FH字节与7H异或,第二个循环是EAX处的地址开始,由于EAX值一直没变,即还是从4010F5H开始的154H字节与11H异或。返回上层,还剩下最后一个函数了,也要跟入(注意,这里这个函数在401039H,是第二个解码位置处)。
这里先对EAX所指的4010F5H处154H字节数据进行累加,和保存在edx中,然后使用40124A和401280H两个值(这两个内存的值未被加密过)作为参数调用了一个40108A处的函数(也未被加密过),接着将之前的累加和edx和一个值比较,不相等的话就会输出CRC *** modified字符串,那几乎可以断定了,这里是计算加密区域是否被修改过,没毛病的话这里会直接跳转到401083H处,而这里又是一个跳转,调到40121EH处,这是第一,三个解码区域,跟着走:
看到这里是一些莫名其妙的东西(好吧,我逆向的第一个程序就有这么一段,完全触及到我的知识盲区了,然后我神奇的用了枚举的方法把它做出来了,下次记录下。。。),这个扰乱代码对齐差不多,OD会自动对程序进行分析,由于这里在分析时是加密后的数据,于是被识别成了数据而非指令,可以禁用分析:
(上下图不同点在于上图未执行到此处,下图是执行到了此处,那么说明跳转前调用的函数可能是载入一个库还是啥的,反正与导入函数有关)
现在有函数名好分析很多了,这里先获取进程句柄,放在403018H处,接着调用DiagBoxParamA,这里用到了4010F5这个东东,它出现了那么多次,去看看:
一些熟悉的字符串。然后就不知道干嘛了。。。。看一眼书,补一下DiagBoxParamA这个函数的知识:
函数原型:int DialogBoxParam(HINSTANCE hInstance,LPCTSTR IpTemplateName,HWND hWndParent, DLGPROC IPDialogFunc,LPARAM dwlnitParam)
参数:
1 | hlnstance:标识一个模块的实例,该模块的可执行文件含有对话框模板。 |
倒是第二个参数即第二个压入栈中的4010F5H是一个对话框过程指针,那就从反汇编窗口观察(在那里下断点,等运行到那里再观察,否则仍然会难以理解):
于是,这里就是我们需要更改的地方,因为这里被加密了两次还计算了校验和,直接在文件里修改有点复杂,可以使用运行时补丁,即当解码完以后再去运行修改代码,这里有个关键点,就是很多其他代码并没有被加密,那样我们修改那部分就会很简单,现在就可以弄补丁代码了。
制作补丁
方法:
- 设置到文件的空白区域
- 扩展最后节区后设置
- 添加新节区后设置
后两种方法需要改PE头的一些东西,这里就用第一种吧。
查看后发现第一节区有可执行权限,在内存中大小为280H字节,说明在磁盘上空了180H,内存中空了780H字节,足够写入补丁代码了!
就是这一段地址,还可以写,而且不用改PE头,完美!那么问题来了,怎么写呢,就是写一段代码把解密后目标字符串改掉,当然不可能直接在文件里面写Opcode,先用od的汇编功能写好再保存到文件就好了,于是,这里在内存中的地址为401280H:
然后开始写代码,将40110AH和401123H处的数据改掉:
(昨天的内容,记下等会用)
那么:
这里没有设置es和ds因为默认的为0,可以不用设置,但是这样写着程序并不会运行到这里,这里需要把解密后,进入解密区域执行的那个跳转放在此段代码尾部,并将那里的跳转地址改为40129E:
似乎昨天说错了,这里也被加密了,看了下是第二区域,与7H异或,所以。。。先等它解密把,再改代码,再异或,毕竟还没有学opcode的读法。。。
更改后
那么就是把401084H处两个字节分别于7异或得23 05,好了,将这些更改写入文件:
………………….我的天,写错了,地址写错了,运行到这里才发现,全部重来,心好痛!!!!
………………….我的天,又写错了,再见。。。。
好了,弹窗没问题了,可以写入文件了
刚才修改的两个地方,文件中偏移分别是:680H和484,可以在文件中直接写入:
1 | 00 00 00 00 42 45 54 41 4D 41 4F 2E 4D 45 00 00 00 00 00 00 4C 41 4C 41 4C 41 4C 41 00 00 56 57 |
和
1 | 23 05 |
也可以直接在od里面修改(注意,此时程序还暂停在入口点,不要运行)
心疼自己,又错了,401083那里的跳转地址算错了,异或出来应该是: 11 05。然后就没问题了!!!!
参考
《逆向工程核心原理》