python使用虚拟内存_Hack 虚拟内存系列(二):Python 字节对象

Hack The Virtual Memory: Python bytes

Hack虚拟内存之第1章:Python 字节对象

在这篇文章中,我们将完成与第0章(C字符串和/proc)几乎相同的事情,但我们将访问正在运行的Python 3脚本的虚拟内存。它不会(像第0章中)那么直接。

并在此过程中看看Python 3的一些内部结构!

前提

本文基于我们在前一章中学到的所有内容。在阅读本文之前,请阅读(并理解)第0章:C字符串和/proc。

为了完全理解本文,你需要知道:

C语言的基础知识

Python的基础知识

Linux文件系统和shell的基础知识

/proc文件系统的基础知识(参见第0章:C字符串和/proc,了解本主题的介绍)

环境

所有脚本和程序都已经在以下系统上进行过测试:

Ubuntu 14.04 LTSLinux ubuntu 4.4.0-31-generic #50~14.04.1-Ubuntu SMP Wed Jul 13 01:07:32 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

gccgcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4

Python 3Python 3.4.3 (default, Nov 17 2016, 01:08:31)

[GCC 4.8.4] on linux

Python脚本

一开始我们将使用此脚本(main.py)并尝试在运行它的进程的虚拟内存中修改字符串“Holberton”。

#!/usr/bin/env python3

'''

Prints a b"string" (bytes object), reads a char from stdin

and prints the same (or not :)) string again

'''

import sys

s = b"Holberton"

print(s)

sys.stdin.read(1)

print(s)

关于字节对象

bytes vs str

如你所见,我们使用一个字节对象(我们在字符串前面使用‘b’前缀)来存储我们的字符串。此类型将以字节的形式存储字符串(与可能的多字节相比 - 你可以阅读unicodeobject.h以了解有关Python 3如何编码字符串的更多信息)。这可确保字符串在运行脚本的进程的虚拟内存中是一连串的ASCII码值。

实际上,s不是Python字符串(但在我们的上下文中并不重要):

julien@holberton:~/holberton/w/hackthevm1$ python3

Python 3.4.3 (default, Nov 17 2016, 01:08:31)

[GCC 4.8.4] on linux

Type "help", "copyright", "credits" or "license" for more information.

>>> s = "Betty"

>>> type(s)

>>> s = b"Betty"

>>> type(s)

>>> quit()

一切都是对象

Python中的所有东西都是一个对象:整数,字符串,字节,函数等等。因此,s = b“Holberton”应该创建一个字节类型的对象,并将字符串b“Holberton”存储在内存中。可能在堆中,因为它必须为对象所引用或存储的字节对象保留空间(此时我们不知道其确切的实现)。

对Python脚本运行read_write_heap.py

注意:read_write_heap.py是我们在上一章第0章:C字符串和/proc中写过的脚本

让我们运行上面的脚本,然后运行我们的read_write_heap.py脚本:

julien@holberton:~/holberton/w/hackthevm1$ ./main.py

b'Holberton'

此时,main.py正在等待用户输入。这对应于我们代码中的sys.stdin.read(1)。

运行read_write_heap.py:

julien@holberton:~/holberton/w/hackthevm1$ ps aux | grep main.py | grep -v grep

julien 3929 0.0 0.7 31412 7848 pts/0 S+ 15:10 0:00 python3 ./main.py

julien@holberton:~/holberton/w/hackthevm1$ sudo ./read_write_heap.py 3929 Holberton "~ Betty ~"

[*] maps: /proc/3929/maps

[*] mem: /proc/3929/mem

[*] Found [heap]:

pathname = [heap]

addresses = 022dc000-023c6000

permisions = rw-p

offset = 00000000

inode = 0

Addr start [22dc000] | end [23c6000]

[*] Found 'Holberton' at 8e192

[*] Writing '~ Betty ~' at 236a192

julien@holberton:~/holberton/w/hackthevm1$

正如所料,我们在堆上找到了字符串(“Holberton”)并替换了它。现在,当我们在main.py脚本中按下Enter键时,它将打印b'~Betty~':

b'Holberton'

julien@holberton:~/holberton/w/hackthevm1$

等一下

我们找到字符串“Holberton”并替换它,但并没有输出正确的字符串?

在我们深入思考前,还有一件事需要检查。我们的脚本在找到第一个字符串后停止。让我们运行几次,看看堆中是否有更多相同的字符串。

julien@holberton:~/holberton/w/hackthevm1$ ./main.py

b'Holberton'

julien@holberton:~/holberton/w/hackthevm1$ ps aux | grep main.py | grep -v grep

julien 4051 0.1 0.7 31412 7832 pts/0 S+ 15:53 0:00 python3 ./main.py

julien@holberton:~/holberton/w/hackthevm1$ sudo ./read_write_heap.py 4051 Holberton "~ Betty ~"

[*] maps: /proc/4051/maps

[*] mem: /proc/4051/mem

[*] Found [heap]:

pathname = [heap]

addresses = 00bf4000-00cde000

permisions = rw-p

offset = 00000000

inode = 0

Addr start [bf4000] | end [cde000]

[*] Found 'Holberton' at 8e162

[*] Writing '~ Betty ~' at c82162

julien@holberton:~/holberton/w/hackthevm1$ sudo ./read_write_heap.py 4051 Holberton "~ Betty ~"

[*] maps: /proc/4051/maps

[*] mem: /proc/4051/mem

[*] Found [heap]:

pathname = [heap]

addresses = 00bf4000-00cde000

permisions = rw-p

offset = 00000000

inode = 0

Addr start [bf4000] | end [cde000]

Can't find 'Holberton'

julien@holberton:~/holberton/w/hackthevm1$

只出现一次。那么脚本中使用的字符串“Holberton”在哪里?Python字节对象在内存中的哪个位置?它可能在栈中吗?在read_write_heap.py脚本中用“[stack]”来替换“[heap]”,创建read_write_stack.py:

(*)参见上一篇文章,栈在/proc/[pid]/maps文件中被称为“[stack]”

#!/usr/bin/env python3

'''

Locates and replaces the first occurrence of a string in the stack

of a process

Usage: ./read_write_stack.py PID search_string replace_by_string

Where:

- PID is the pid of the target process

- search_string is the ASCII string you are looking to overwrite

- replace_by_string is the ASCII string you want to replace

search_string with

'''

import sys

def print_usage_and_exit():

print('Usage: {} pid search write'.format(sys.argv[0]))

sys.exit(1)

# check usage

if len(sys.argv) != 4:

print_usage_and_exit()

# get the pid from args

pid = int(sys.argv[1])

if pid <= 0:

print_usage_and_exit()

search_string = str(sys.argv[2])

if search_string == "":

print_usage_and_exit()

write_string = str(sys.argv[3])

if search_string == "":

print_usage_and_exit()

# open the maps and mem files of the process

maps_filename = "/proc/{}/maps".format(pid)

print("[*] maps: {}".format(maps_filename))

mem_filename = "/proc/{}/mem".format(pid)

print("[*] mem: {}".format(mem_filename))

# try opening the maps file

try:

maps_file = open('/proc/{}/maps'.format(pi

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值