[转]Data Structure Recovery using PIN and PyGraphviz
Source:http://v0ids3curity.blogspot.com/2015/04/data-structure-recovery-using-pin-and.html
--------------------------------
Data Structure Recovery using PIN and PyGraphviz
Tracing Size and Address of Allocations
Size of Allocation
Right now, we track libc functions malloc, realloc, calloc, sbrk, mmap and free. All these routines are instrumented using Rtn_InsertCall to fetch the size of requested allocation.
For example, for tracing malloc
- RTN_InsertCall( rtn,
- IPOINT_BEFORE,
- (AFUNPTR)AllocBefore,
- IARG_ADDRINT,
- funcname,
- IARG_G_ARG0_CALLEE,
- IARG_RETURN_IP,
- IARG_END);
We fetch the size of requested allocation using IARG_G_ARG0_CALLEE and IPOINT_BEFORE. Also, we need to identify the malloc calls that are only called from our main executable. To find this we use IARG_RETURN_IP to check if the return address of the call is part of main executable, if not we don't trace the allocation.
Address of Allocation
IARG_RETURN_IP is valid only at function entry point, so we cannot use IPOINT_AFTER along with IARG_RETURN_IP. As a work around, we save the return address during IPOINT_BEFORE. Then in instruction trace, if instruction pointer equals return address of an allocation call, we fetch the EAX value. This gives the address of allocation.
- if(insaddr == retaddress){
- INS_InsertCall( ins,
- IPOINT_BEFORE,
- (AFUNPTR)AllocAfter,
- #ifdef __i386__
- IARG_REG_VALUE, LEVEL_BASE::REG_EAX,
- #else
- IARG_REG_VALUE, LEVEL_BASE::REG_RAX,
- #endif
- IARG_END);
- }
Now we have both address and size of allocation. These details are stored as dictionary as pairs of address : size. Also we don't remove an address when free is called upon that, instead if an already existing address is returned during an allocation call ie. reallocation, we just update the size of existing allocation for the new allocation request.
- if(allocations.count(address)==0){
- allocations.insert(std::make_pair(address, allocsize));
- }
- else{
- std::map<addrint, addrint="" style="font-size: 14px;">::iterator it = allocations.find(retval);
- it->second = allocsize;
- }
.data and .bss sections
data and bss sections are also added to dictionary. The size and address of these segments are fetched from main executable and added as part of allocations
- if(!strcmp(sec_name.c_str(),".bss")||!strcmp(sec_name.c_str(),".data")){
- ADDRINT addr = SEC_Address(sec);
- USIZE size = SEC_Size(sec);
- if(allocations.count(addr)==0){
- allocations.insert(std::make_pair(addr, size));
- }
- }
Tracing Memory Writes
We trace instructions that writes into the allocated memory. As of now only XED_ICLASS_MOV class of instructions are traced. For all XED_ICLASS_MOV instruction, we check if its a memory write instruction using INS_IsMemoryWrite and is part of main executable.
In this case, we fetch the destination address of write operation using IARG_MEMORYWRITE_EA. Then we check if the destination address is part of any allocation, on success this instruction is traced.
- for(it = allocations.begin(); it != allocations.end(); it++){
- if((des_addr >= it->first)&&(des_addr < it->first+it->second))returntrue;
- }
Sample Trace
- .data[0x804b02c,0x8]
- .bss[0x804b040,0xfc4]
- 0x8048560@sbrk[0x420]
- ret[0x98de000]
- 0x8048565@mov dword ptr [0x804c000], eax : WRREG MEM[0x804c000] VAL[0x98de000]
- 0x8048575@mov dword ptr [eax+0x8],0x0 : WRIMM MEM[0x98de008] VAL[0]
- 0x804857f@mov dword ptr [edx+0x4], eax : WRREG MEM[0x98de004] VAL[0]
- 0x8048587@mov dword ptr [eax],0x10 : WRIMM MEM[0x98de000] VAL[0x10]
- 0x80485a0@mov dword ptr [eax+0x4], edx : WRREG MEM[0x98de004] VAL[0x98de010]
- 0x80485ac@mov dword ptr [eax+0x8], edx : WRREG MEM[0x98de018] VAL[0x98de000]
Graphing
Node Create
For each allocation in trace file generated by PIN tool, a new node is created in the graph. Each node is uniquely identified using a node id which is assigned sequentially. An ordered dictionary is maintained, key being node id and value is dictionary of address and size of allocation. New allocations are added to the start of ordered dictionary.
An edge count is associated with each of created node. This will be used for pruning away nodes without any edges.
Separate nodes are created for bss and data sections. But this is optional.
Example
Say a structure is allocated in heap using malloc, this is how a node will look like
- 0x80488c5@malloc[0x20]
- ret[0x8fcf030]
- -------------------
- |[0]0x8fcf030 |
- -------------------
[0] is the node id, this could signify the order of allocation. Every new allocator call gets a new id, irrespective of the return address
0x8fcf030 is the address returned by allocator call
Node Update
For each instruction, fetch the target address of write operation. If the target address is part of any allocation, update the node to which the target address belongs to. Basically we create a new port in the record node.
A new port signifies an element of an allocation, say element of a structure.
Then check if the source value is part of any allocation. If yes, we consider the source value as an address. Then update the node to which the source address belongs to. This operation could be interpreted as a pointer assignment [or link creation]
- 0x80488c5@malloc[0x20]
- ret[0x8fcf030]
- 0x8048957@movbyte ptr [eax+edx*1],0x0 : WRIMM MEM[0x8fcf031] VAL[0]
- 0x80489bb@mov dword ptr [eax+0x14], edx : WRREG MEM[0x8fcf044] VAL[0x8fcf058]
- 0x8048a40@mov dword ptr [eax+0x18], edx : WRREG MEM[0x8fcf048] VAL[0x8fcf008]
- 0x8048a4e@mov dword ptr [eax+0x1c], edx : WRREG MEM[0x8fcf04c] VAL[0x8fcf008]
- -------------------------------------------------------------------------
- |[0]0x8fcf030 |0x8fcf031 |0x8fcf044 | 0x8fcf048 | 0x8fcf04c |
- -------------------------------------------------------------------------
Now first field [0] 0x8fcf030 is the meta data for the chunk ie node id and return address of allocator call. The rest of 4 fields signifies 4 individual write operations into this allocation [example, 4 elements of a structure]
Create Link
If both source and destination values are valid address and belongs to a traced allocation, we link both ports of the nodes. Whenever a link is created, edge count of source and destination are incremented.
Similarly, during memory overwrite an edge is removed and edge count is decremented.
Example,
- 0x804882a@malloc[0x20]
- ret[0x8fcf008]
- …...
- 0x80488c5@malloc[0x20]
- ret[0x8fcf030]
- …...
- 0x80489bb@mov dword ptr [eax+0x14], edx : WRREG MEM[0x8fcf044] VAL[0x8fcf058]
- 0x8048a40@mov dword ptr [eax+0x18], edx : WRREG MEM[0x8fcf048] VAL[0x8fcf008]
- 0x8048a4e@mov dword ptr [eax+0x1c], edx : WRREG MEM[0x8fcf04c] VAL[0x8fcf008]
Above is a series of pointer writes into memory allocated at 0x8fcf030. The address points to another allocation at 0x8fcf008. Hence we link both
Prune Node
Finally after parsing all instructions, remove nodes that doesn't have any edges. For this, check if the edge count for a node is 0. If yes, remove the node.
Other Options
By default, we consider only the first non-NULL write operation for node update and link creation. This might be good enough to reveal some of data structures. Any memory writes to an address after first write non-NULL are skipped. But one can use relink option to consider more than single write operation for graphing. This could be useful when relink operations are done, say circular linked list.
NULL writes can also be enabled as option. This might be useful along with relink.
The tool itself doesn't itself have the intelligence to say what data structure is used, but can graph the allocation and links to help someone understand a data structure from the revealed shape.
Example - Singly Linked List

Example - Binary Tree

Example - HackIM Mixme Circular Doubly Linked List

The POC code which I use for CTF is available here. To repeat again, this works on small binaries, as things get complex the graph might make less sense. There is lot of scope for improvement though.
References
AES Whitebox Unboxing: No Such Problem, this served as excellent reference for the usage of PIN tool and pygraphviz to visualize memory access
Thanks to Danny K, for help with Intel PIN Framework.
[转]Data Structure Recovery using PIN and PyGraphviz的更多相关文章
- [LeetCode] All O`one Data Structure 全O(1)的数据结构
Implement a data structure supporting the following operations: Inc(Key) - Inserts a new key with va ...
- [LeetCode] Add and Search Word - Data structure design 添加和查找单词-数据结构设计
Design a data structure that supports the following two operations: void addWord(word) bool search(w ...
- [LeetCode] Two Sum III - Data structure design 两数之和之三 - 数据结构设计
Design and implement a TwoSum class. It should support the following operations:add and find. add - ...
- Finger Trees: A Simple General-purpose Data Structure
http://staff.city.ac.uk/~ross/papers/FingerTree.html Summary We present 2-3 finger trees, a function ...
- Mesh Data Structure in OpenCascade
Mesh Data Structure in OpenCascade eryar@163.com 摘要Abstract:本文对网格数据结构作简要介绍,并结合使用OpenCascade中的数据结构,将网 ...
- ✡ leetcode 170. Two Sum III - Data structure design 设计two sum模式 --------- java
Design and implement a TwoSum class. It should support the following operations: add and find. add - ...
- leetcode Add and Search Word - Data structure design
我要在这里装个逼啦 class WordDictionary(object): def __init__(self): """ initialize your data ...
- Java for LeetCode 211 Add and Search Word - Data structure design
Design a data structure that supports the following two operations: void addWord(word)bool search(wo ...
- HDU5739 Fantasia(点双连通分量 + Block Forest Data Structure)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5739 Description Professor Zhang has an undirect ...
随机推荐
- jsmart 前结合案例
前绑定jsmart这是一个不错的选择.之前通过经常使用的项目中的.最近涉及的领域的后端部.jsmart有些使用相对较少,主要是因为他想引用文件,我写的模板,在一个简单的项目,直接使用js界,很复杂的前 ...
- JS如何判断包括IE11在内的IE浏览器
原文:JS如何判断包括IE11在内的IE浏览器 今天碰到一个奇怪的问题,有一个页面,想指定用IE浏览器打开,在VS开发环境没有问题,但部署到服务器上,即使是用IE打开页面,还是提示"仅支持I ...
- sql server中的索引详情
什么是索引 拿汉语字典的目录页(索引)打比方:正如汉语字典中的汉字按页存放一样,SQL Server中的数据记录也是按页存放的,每页容量一般为4K .为了加快查找的速度,汉语字(词)典一般都有按拼音. ...
- 实战parse_ini_file()及扩展函数解析ini文件完整版
文章来源:PHP开发学习门户 地址:http://www.phpthinking.com/archives/587 在PHP站点开发的过程中,往往会用到读取ini參数配置文件,比方须要訪问一些复杂的借 ...
- 出现localStorage错误Link解决方案(组态)
属性-链接-进入-附加依赖-加入sqlite3.lib cocos2d-x-2.2.2\Debug.win32添加的文件夹sqlite3.dll.sqlite3.lib 版权声明:本文博客原创文章.博 ...
- style中position的属性值具体解释
Position的英文原意是指位置.职位.状态.也有安置的意思.在CSS布局中,Position发挥着非常关键的数据,非常多容器的定位是用Position来完毕. Position属性有四个可选值,它 ...
- UVA The Sultan's Successors
题目例如以下: The Sultan's Successors The Sultan of Nubia has no children, so she has decided that thecou ...
- 工欲善其事:编辑器之神Vim(一)
本篇文章收集了Vim最常用和实用的一些命令,掌握这些命令就可以使用Vim了 本文仅列举个人认为常用的命令,本系列文章更像是自己的学习笔记,而不是VIM使用教程. 如果你想了解vim的更多,可以看看Co ...
- Linux下使用Photorec恢复误格U盘
photorec包含在testdisk软件包中, 所以直接通过包管理器直接安装testdisk安装即可. 使用root权限来运行软件,在终端键入 [shell] photorec [/shell] 然 ...
- hibernate在持久对象的生命周期(三州:自由状态,持久状态,自由状态 之间的转换)
三种状态的基本概念: 1. 临时身份(Transient):也被称为自由状态,它只存在于内存中,并且在数据库中没有相应的数据. 使用new创建的对象,久化,没有处于Session中,处于此状态的对象 ...