首页
社区
课程
招聘
[原创]Python源码解析-builtin_function_or_method
发表于: 2023-3-15 20:56 6344

[原创]Python源码解析-builtin_function_or_method

2023-3-15 20:56
6344

builtin_function_or_method对象

上一节已经了解到PyCodeObject,我们的Python代码最终会生成该类对象,参与执行。但Python中有很多函数是由原生C代码提供的,如:os,getcwd()。通过type查看该类函数的类型,可得到以下结果:

 

 

和之前的function对象不同,这类函数并没有co_code对象,他们的代码实现都是基于C代码编译而来。那么这些代码在哪呢?

 

在\Modules\posixmodule.c下,可以找到INITFUNC。这里的代码创建了初始化了一个Module对象。

 

 

注意,这里函数名称是个宏,宏定义如下:

 

文本 描述已自动生成

 

在Windows平台下,这个模块名称叫nt,其他平台就是posix。实际上,我们在Python代码中,完全可以通过import来使用该Module。并不会报错找不到。

 

 

在写Python的时候,经常会使用到一个名称为os的模块。通过dir看一下nt和os的成员。

 

文本 描述已自动生成

 

文本 描述已自动生成

 

可以看到有很多函数都在nt和os里,可以通过以下代码查看,可以发现nt.getcwd和os.getcwd的id地址是一样,绝大部分这类函数的地址都是一样的。

 

 

接下来看一下posixmodule对象。他是PyModuleDef结构类型,其中有个成员m_methods。这里就记录了很多函数结构。

 

文本 描述已自动生成

 

变量posix_methods是由多个PyMethodDef对象组成的数字,以空PyMethodDef对象为结尾。

 

文本 描述已自动生成

 

随意看一个PyMethodDef对象,其有四个成员组成。第一个是函数名,Python代码是通过这个函数名来调用相应函数。第二个成员就是对应的函数地址。第三个是函数flags(含义可查看源码)。第四个是对该函数的说明字符串。

 

Python系统函数

了解到os.getcwd函数是怎么来的。那么再来看Python系统提供的函数,如:print。这类函数的定义在Python\bltinmodule.c中可以找到。同nt模块,我们可以找到一个builtins模块。该模块是Python最基础的模块。

 

文本 描述已自动生成

 

同样builtin_methods是一个PyMethodDef数组,以空PyMethodDef结尾。熟悉的print、dir等函数都可在这找到定义。

 

文本 描述已自动生成

 

这类Moudle还有很多,如io模块也是这样实现的。在Modules\_io\_iomodule.c可找到对应的定义。

3.内存中的builtin_function_or_method

Python提供了一个叫id的函数,该函数可以查看对应对象在内存中的地址。接下来以open函数为例,来找open函数的代码地址。

 

首先通过id获取open函数对象地址。

 

文本 描述已自动生成

 

到内存中查看此地址。根据之前PyMethodDef的结构,可以知道第二个成员内记录了函数的代码地址。

 

 

所以访问第二个成员地址,0x7ff91925bf40。

 

文本 描述已自动生成

 

在PyMethodDef中可以看到一个宏_PyCFunction_CAST。该宏是创建一个PyCFunction对象,宏定义如下:

 

 

PyCFunction其只有一个成员,那就是函数的代码地址。内存访问0x7ff91925bf40。得到函数代码地址0x7ff918b0bf40。

 

图形用户界面 中度可信度描述已自动生成

 

在监视器内查看_io_open代码地址。是一致的,证明找对了。

 

图片包含 图形用户界面 描述已自动生成

4.扩展编程

了解到上述结构后,通过Python代码来修改某个函数代码地址,来执行shellcode。

  1. 先准备一个shellcode。Shellcode会打开一个notepad。

文本 描述已自动生成

  1. 找到shellcode在内存中的地址。

文本 描述已自动生成

 

3.这段数据现在是只读,所以需要修改一下内存属性。

 

徽标 低可信度描述已自动生成

 

4.获取os.getcwd代码地址在PyCFunction中的地址。

 

文本 描述已自动生成

 

5.修改PyCFunction中os.getcwd代码地址,替换为shellcode的地址。

 

文本 描述已自动生成

 

6.执行os.getcwd()。可发现shellcode成功执行。

 

5.总结

这个的玩法还有很多,执行hook、添加自己的函数等功能都可以。但要注意的是,涉及的内存都是只读属性,需要修改内存属性才可修改。VirtualProtect是一个很明显的动作,如果是想要来搞坏事,就要多注意一下。


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 424
活跃值: (946)
能力值: ( LV5,RANK:75 )
在线值:
发帖
回帖
粉丝
2
基于此,之后搞个cm发出来试试
2023-3-15 21:02
1
游客
登录 | 注册 方可回帖
返回
//