论菜鸡pwn手如何在无网环境(ps:类似国赛)下生存
引言:在打完一次无网环境后,觉得没网环境实在难受,查个libc都没得查。。没准备好,那时碰巧我下了ctf-challenge,在那里碰巧弄到了libc,可能有人喜欢用libc-searcher那个py版本的项目,我不怎么喜欢,用那个导入库查找感觉较慢,还是喜欢手动泄露后到网页查找,于是有了这篇文章
pwntools安装
pip install pwntools
出错自己解决啊,那些个错误都查得到
one_gadget
gem install one_gadget
gdb配置
我个人觉得,peda和pwndbg必备,gef也可以用上,随你
自己写了个脚本,很渣,自选用不用
项目地址
三个插件一起用会冲突,一部分功能失效,建议注释掉.gdbinit里的gef部分
welpwn
这个项目是国防科技大学弄的,挺好用的,最主要是能加载libc
git clone https://github.com/matrix1001/welpwn
到项目目录下然后
sudo python setup.py install
用法你可以看他项目里的介绍
ctf-wiki本地搭建
作为一个不是啥都熟的选手,ctf-wiki还是必备的,打比赛的时候查查exp,查查用法什么都好
首先安装docker
这个不讲了
docker pull镜像
docker search ctf #先查找镜像,镜像名知道可以不查找
docker pull ctfwiki/ctf-wiki #pull ctfwiki镜像
docker run -d --name=ctf-wiki -p 4100:80 ctfwiki/ctf-wiki #-d参数为后台运行,--name为名称 -p为端口映射 4100是本地端口,80是docker端口
部署libc-database
docker pull blukat29/libc
docker run -p 4101:80 -d blukat29/libc
配置文件目录/etc/nginx/conf.d/nginx.conf
启动端口在4101,这里有个小问题,就是无法下载,解决方法,替换nginx的配置文件为如下
server {
location / {
try_files $uri @app;
}
location @app {
include uwsgi_params;
uwsgi_param Host $host;
uwsgi_param X-Real-IP $remote_addr;
uwsgi_param X-Forwarded-For $proxy_add_x_forwarded_for;
uwsgi_pass unix:///tmp/uwsgi.sock;
}
location /static {
alias /app/static;
}
location /d {
alias /libc-database/db;
location ~ \.symbols$ {
default_type text/plain;
}
}
}
最主要是
location /d {
alias /libc-database/db;
location ~ \.symbols$ {
default_type text/plain;
}
}
然后发觉每次重启都会他配置文件都会重置,研究下了他docker里的东西,发觉是entrypoint.sh影响了,所以修改下entrypoint.sh就行
#! /usr/bin/env bash
set -e
# Get the maximum upload file size for Nginx, default to 0: unlimited
USE_NGINX_MAX_UPLOAD=${NGINX_MAX_UPLOAD:-0}
# Generate Nginx config for maximum upload file size
echo "client_max_body_size $USE_NGINX_MAX_UPLOAD;" > /etc/nginx/conf.d/upload.conf
# Get the number of workers for Nginx, default to 1
USE_NGINX_WORKER_PROCESSES=${NGINX_WORKER_PROCESSES:-1}
# Modify the number of worker processes in Nginx config
sed -i "/worker_processes\s/c\worker_processes ${USE_NGINX_WORKER_PROCESSES};" /etc/nginx/nginx.conf
# Get the URL for static files from the environment variable
USE_STATIC_URL=${STATIC_URL:-'/static'}
# Get the absolute path of the static files from the environment variable
USE_STATIC_PATH=${STATIC_PATH:-'/app/static'}
# Get the listen port for Nginx, default to 80
USE_LISTEN_PORT=${LISTEN_PORT:-80}
# Generate Nginx config first part using the environment variables
echo "server {
listen 80;
location / {
try_files \$uri @app;
}
location @app {
include uwsgi_params;
uwsgi_param Host \$host;
uwsgi_param X-Real-IP \$remote_addr;
uwsgi_param X-Forwarded-For \$proxy_add_x_forwarded_for;
uwsgi_pass unix:///tmp/uwsgi.sock;
}
location /static {
alias /app/static;
}
location /d {
alias /libc-database/db;
location ~ \.symbols$ {
default_type text/plain;
}
}" > /etc/nginx/conf.d/nginx.conf
# If STATIC_INDEX is 1, serve / with /static/index.html directly (or the static URL configured)
if [[ $STATIC_INDEX == 1 ]] ; then
echo " location = / {
index $USE_STATIC_URL/index.html;
}" >> /etc/nginx/conf.d/nginx.conf
fi
# Finish the Nginx config file
echo "}" >> /etc/nginx/conf.d/nginx.conf
exec "$@"
然后就部署完成了,如果还嫌麻烦,可以用下我这个Dockerfile
项目地址
用法在项目里已经说明了,只是修改了一点点错误
者本地搭建ctf-all-in-one
https://github.com/firmianay/CTF-All-In-One
下载项目
git clone https://github.com/firmianay/CTF-All-In-One
GitBook基础
README.md和SUMMARY.md
必备文件
利用Docker安装Gitbook
docker search gitbook #可以查看,我用了最高星的那个
docker pull fellah/gitbook
先到项目的目录下
然后
docker run -v $PWD:/srv/gitbook -v $PWD/html:/srv/html fellah/gitbook gitbook build . /srv/html
展示Gitbook文件
因为生成的是html静态页面所以需要一个web服务来显示,我用nginx
docker pull nginx
docker run --name ctf-all-in-one -v /$PWD/html:/usr/share/nginx/html -d -p 4102:80 nginx
这样就搭建完成了
访问你自己的4100-4102端口看下,是否成功了
下载ctf-challenge,例题以及exp
git clone https://github.com/ctf-wiki/ctf-challenges
这个说不定哪天就用上了,说不准
exp模板构建
因为要快速做题,每次重复的部分整合起来比较好,所以便研究下exp模板如何弄,我是通过修改pwntools里自带的exp模板,生成自己专属的模板的,我建议都弄成自己的exp模板类型吧,因为每个人代码风格不一样,没必要一定用大佬的模板,当然有可能大佬的模板好,但不一定适合自己
模板位置
第一个是模板的具体内容,第二个是生成模板的方法
- pwnup.mako
- template.py
你可以find / -name 名称
找到具体位置,最好先备份一份
具体配置自行配置,因为每个人风格不同
pwntools exp模板自定义
<%page args="binary, host=None, port=None, libc=None, local=True"/>\
<%
import os
import sys
from pwnlib.context import context as ctx
from pwnlib.elf.elf import ELF
from pwnlib.util.sh_string import sh_string
from elftools.common.exceptions import ELFError
argv = list(sys.argv)
argv[0] = os.path.basename(argv[0])
try:
if binary:
ctx.binary = ELF(binary, checksec=False)
except ELFError:
pass
if not binary:
binary = './path/to/binary'
exe = os.path.basename(binary)
binary_repr = repr(binary)
libc_repr = repr(libc)
%>\
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from PwnContext.core import *
local = True
%if ctx.binary:
# Set up pwntools for the correct architecture
exe = './' + ${binary_repr}
elf = context.binary = ELF(exe)
<% binary_repr = 'exe.path' %>
%else:
context.update(arch='i386')
exe = ${binary_repr}
<% binary_repr = 'exe' %>
%endif
#don't forget to change it
%if host:
host = args.HOST or ${repr(host)}
%else:
host = '127.0.0.1'
%endif
%if port:
port = int(args.PORT or ${port})
%else:
port = 10000
%endif
#don't forget to change it
#ctx.binary = './' + ${repr(binary)}
ctx.binary = exe
%if not libc:
libc = elf.libc
ctx.debug_remote_libc = False
%else:
libc = args.LIBC or ${libc_repr}
ctx.debug_remote_libc = True
%endif
ctx.remote_libc = libc
if local:
context.log_level = 'debug'
try:
io = ctx.start()
except Exception as e:
print(e.args)
print("It can't work,may be it can't load the remote libc!")
print("It will load the local process")
io = process(exe)
else:
io = remote(host,port)
#===========================================================
# EXPLOIT GOES HERE
#===========================================================
%if ctx.binary and not quiet:
# ${'%-10s%s-%s-%s' % ('Arch:',
ctx.binary.arch,
ctx.binary.bits,
ctx.binary.endian)}
%for line in ctx.binary.checksec(color=False).splitlines():
# ${line}
%endfor
%endif
def exp():
pass
if __name__ == '__main__':
exp()
io.interactive()
具体语法可以理解为
%if args
content
%endif
content就是内容,args就是参数,通过这个方法进行模板的生成
pwntools exp模板生成方法
#!/usr/bin/env python2
from __future__ import absolute_import
import re
from pwn import *
from pwnlib.commandline import common
from mako.lookup import TemplateLookup
parser = common.parser_commands.add_parser(
'template',
help = 'Generate an exploit template'
)
parser.add_argument('exe', nargs='?', help='Target binary')
parser.add_argument('--host', help='Remote host / SSH server')
parser.add_argument('--port', help='Remote port / SSH port', type=int)
parser.add_argument('--libc', help='Remote libc version')
parser.add_argument('--local', help='local debug', action='store_true')
def main(args):
cache = None
if cache:
cache = os.path.join(context.cache_dir, 'mako')
lookup = TemplateLookup(
directories = [os.path.join(pwnlib.data.path, 'templates')],
module_directory = cache
)
template = lookup.get_template('pwnup.mako')
output = template.render(args.exe,
args.host,
args.port,
args.libc,
args.local,
)
# Fix Mako formatting bs
output = re.sub('\n\n\n', '\n\n', output)
print output
if not sys.stdout.isatty():
try: os.fchmod(sys.stdout.fileno(), 0700)
except OSError: pass
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
最终效果
└──╼ $pwn template oreo --libc libc.so.6
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from PwnContext.core import *
local = True
# Set up pwntools for the correct architecture
exe = './' + 'oreo'
elf = context.binary = ELF(exe)
#don't forget to change it
host = '127.0.0.1'
port = 10000
#don't forget to change it
#ctx.binary = './' + 'oreo'
ctx.binary = exe
libc = args.LIBC or 'libc.so.6'
ctx.debug_remote_libc = True
ctx.remote_libc = libc
if local:
context.log_level = 'debug'
try:
io = ctx.start()
except Exception as e:
print(e.args)
print("It can't work,may be it can't load the remote libc!")
print("It will load the local process")
io = process(exe)
else:
io = remote(host,port)
#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# Arch: i386-32-little
# RELRO: No RELRO
# Stack: Canary found
# NX: NX enabled
# PIE: No PIE (0x8048000)
def exp():
pass
if __name__ == '__main__':
exp()
io.interactive()