实例程序
1.主函数:
一个64位的linux程序,ida查看函数逻辑:
flag被分成两半进行验证,前半段的验证函数为left_check,后半段函数使用了SMC,这里分析一下具体操作:
- 首先调用mmap函数开辟一段内存空间
- addr:指定映射的起始地址,通常设为NULL,由内核来分配
- length:代表将文件中映射到内存的部分的长度。
- prot:映射区域的保护方式。可以为以下几种方式的组合:
- PROT_EXEC 映射区域可被执行
- PROT_READ 映射区域可被读取
- PROT_WRITE 映射区域可被写入
- PROT_NONE 映射区域不能存取
- flags:映射区的特性标志位,常用的两个选项是:
- MAP_SHARD:写入映射区的数据会复制回文件,且运行其他映射文件的进程共享
- MAP_PRIVATE:对映射区的写入操作会产生一个映射区的复制,对此区域的修改不会写会原文件
- fd:要映射到内存中的文件描述符,有open函数打开文件时返回的值。
- offset:文件映射的偏移量,通常设置为0,代表从文件最前方开始对应,offset必须是分页大小的整数倍。
mmap函数用法分析
参数介绍:
函数返回值:实际分配的内存的起始地址。
- cipher()函数先对函数代码解密。
- memcpy()函数将解密的代码放入之前开辟的空间
- 将后半段flag传入刚刚自解密出来的函数,这里应该是对后半段flag进行加密。
- 最后调用right_check()函数对加密后的后半段flag进行验证。
2.前半段Flag解密:
看到wasd判断这可能是个迷宫问题,跟踪数组
aAB
,其值以放在了注释中,将它手工改成一个二维地图:
从A点出发到达B点,*号为墙壁,而且看地图可知只有一条路可走:
ssddddwddddsss
但是这里还需要注意的是长度要求为15,在后面随便再补一个字符即可
ssddddwddddsss
接着是flag的后半段。
3.后半段flag解密:
先看一下自解密函数:
第一个循环中byte_404080处的数据异或上byte_404360处的数据解密出程序代码。在第二个循环解密了一串字符串,这里动调直接看一下解密后的函数与字符串:

上图就是自解密后的函数可以发现是常规的base64编码,然后查看cipher()函数查看解密后的那64位字符串:

这个字符串大概率就是当base64的码表来用了,接着查看right_check()函数:
看到这里思路大概就明朗了,后半段的flag做了一次换了码表的base64编码,得出来的结果若为
r60ihyZ/m4lseHt+m4t+mIkc
则表示后半段flag输入正确,用脚本快速解密:
至此flag就解出来了:
ssddddwddddsss-J1aR@j1w@nch1sh3m3