在上一篇文章中提到一个问题就是加载的文件不知道哪里去了,虽然用id()函数可以看到加载的地址。但是这个地址在访问的时候却是要么地址不可用,要么就是和文件中的数据不同。于是直接用Python测试了一下。测试代码就是上面的样子。
用ImmDbg挂在python.exe,在内存中访问上面得到的地址。需要注意的是,在python.exe模块中是无法访问到这个地址的,要切换到python26.dll模块中。对应的内存地址如下:
通过id得到的是变量的地址不错,但是这个是一个结构体,如果没猜错应该是下面这个东东:
#define PyBytesObject PyStringObject
typedef struct {
PyObject_VAR_HEAD
long ob_shash;
int ob_sstate;
char ob_sval[1];
/* Invariants:
* ob_sval contains space for 'ob_size+1' elements.
* ob_sval[ob_size] == 0.
* ob_shash is the hash of the string or -1 if not computed yet.
* ob_sstate != 0 iff the string object is in stringobject.c's
* 'interned' dictionary; in this case the two references
* from 'interned' to this object are *not counted* in ob_refcnt.
*/
} PyStringObject;
所以本质上Bytes和String是一个东东,现在来看看这个猜测对不对。
按照定义对这篇内存进行分析:
但是对应的内存中的数据最后的hash 为FFFFFFFF。在通过上面的计算之后Python却又将这个数据给更新了。如下图:
对应的文件数据位于+0x14处。这也就是文件加载到内存之后的内存对应的数据。同样通过分配的内存可以看出整个结构结构体的头部和数据的关系:0xa6=0x90+0x14+0x2(结束符)
虽然直接在python中整个数据非常直观,干事在ImmDbg调试器中去找这个东西却又找不到了,因为进程没有加载python模块。话说谁知道这个东东怎么找?还望不吝赐教。
怎么发现越分析越蛋疼嗫。
6 comments
Python的字符串有interned机制,
具体参考stringobject.c -> PyString_InternInPlace
顺着interned可以找到全部字符串
我已经找到了,但是我说的那个还是没找到。头文件定义的东西在找那个东西的时候并没有太大的帮助。
你说的那个没找到?具体指什么?
我说的方法仅供参考,因为我没用过ImmDbg,我只会OD.
还有个方法就是debug编译Python,这样子每个PyObject里面会包含next和prev指针,一样可以顺藤摸瓜.
Python对象有个特点就是不可变性,以及Python内部的一些加速的机制,所以对于一些数据的话,还是有迹可循的.
调试器执行py代码加载的文件在什么地方?
read的时候,调用了fileobject.c -> file_read() -> Py_UniversalNewlineFread()
Py_UniversalNewlineFread的第一个参数就是PyStringObject的ob_sval
file_read() 的返回值就是PyStringObject
你还是没明白我什么意思,直接用python加载我自然知道文件在哪里,我的意思是调试器的脚本执行的时候通过脚本加载的文件在什么地方。我要找的不是在python命令行中找那个文件,也不是直接运行py文件加载的文件,我是要在调试器中找到那个东西。