I made this simple assembly program:
.text
.globl _start
_start:
mov %20, %rbx
mov %1, %rax
int $0x80
This is obviously running on a 64 bit OS (Linux). I then compiled it as follows:
as -o ExitShellcode.o ExitShellcode.s
ld -o ExitShellcode ExitShellcode.o
And finally after running the program, It exits with a status of 20
echo $?
20
Using objdump to dump the shellcode for the file gives:
objdump -d ExitShellcode
ExitShellcode: file format elf64-x86-64
Disassembly of section .text:
0000000000400078 <_start>:
400078: 48 c7 c3 14 00 00 00 mov $0x14,%rbx
40007f: 48 c7 c0 01 00 00 00 mov $0x1,%rax
400086: cd 80 int $0x80
However, after putting the shellcode in this program:
#include <stdio.h>
char shellcode[] = "\x48\xc7\xc3\x14\x00\x00\x00"
"\x48\xc7\xc0\x01\x00\x00\x00"
"\xcd\x80";
int main()
{
int *ret;
ret = (int *)&ret +2;
*ret = (int)shellcode;
}
and compiling:
gcc -g -o Shellcode Shellcode.c
Shellcode.c: In function ‘main’:
Shellcode.c:13:9: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
*ret = (int)shellcode;
and running, the program exits with a 0 status:
echo $?
0
What's the proplem? Shouldn't it exit with a 20?
Your code incorrectly assumes that the compiler will put the variable ret at a certain place on the stack relative to the return address of main. Instead the compiler put it somewhere else, as it is allowed to do, and so your code does nothing. Your probably following a badly designed example you found on the Internet.
If you want to execute the "shellcode" in the shellcode array you can try casting to it a pointer to function and then calling it:
char shellcode[] = "\x48\xc7\xc3\x14\x00\x00\x00"
"\x48\xc7\xc0\x01\x00\x00\x00"
"\xcd\x80";
int main()
{
((void (*)()) shellcode)();
}
However this will still probably fail because the .data section where shellcode is placed isn't executable and so the program will crash when run. To fix that problem use the -zexecstack option when linking your program. For example:
gcc -zexecstack -g -o Shellcode Shellcode.c
Related
I'm trying to run this shellcode but I keep getting segmentation fault
/* call_shellcode.c */
/*A program that creates a file containing code for launching shell*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
const char code[] =
"\x31\xc0" /* Line 1: xorl %eax,%eax */
"\x50" /* Line 2: pushl %eax */
"\x68""//sh" /* Line 3: pushl $0x68732f2f */
"\x68""/bin" /* Line 4: pushl $0x6e69622f */
"\x89\xe3" /* Line 5: movl %esp,%ebx */
"\x50" /* Line 6: pushl %eax */
"\x53" /* Line 7: pushl %ebx */
"\x89\xe1" /* Line 8: movl %esp,%ecx */
"\x99" /* Line 9: cdq */
"\xb0\x0b" /* Line 10: movb $0x0b,%al */
"\xcd\x80" /* Line 11: int $0x80 */
;
int main(int argc, char **argv)
{
char buf[sizeof(code)];
strcpy(buf, code);
((void(*)( ))buf)( );
}
I compile it using:
gcc -z execstack -o call_shellcode call_shellcode.c
and
gcc -fno-stack-protector -z execstack -o call_shellcode call_shellcode.c
But I keep getting segmentation fault
Also, I'm running a 64 bit Linux system (ubuntu)
You are using a 32 bit assembly code on a x86-64 system. So, It is your problem, you have to create your shellcode for x86-64 systems.
E.g.
400078: 48 31 c0 xor rax,rax
40007b: 48 bf 2f 2f 62 69 6e movabs rdi,0x68732f6e69622f2f
400082: 2f 73 68
400085: 48 31 f6 xor rsi,rsi
400088: 56 push rsi
400089: 57 push rdi
40008a: 48 89 e7 mov rdi,rsp
40008d: 48 31 d2 xor rdx,rdx
400090: b0 3b mov al,0x3b
400092: 0f 05 syscall
One of the main differences with 32 bits assembly, is how to use the syscalls. In this link Linux Syscalls x86-64 you can see what registers you need to call the sys_execve
int execve(const char *filename, char *const argv[],
char *const envp[]);
const char *filename -> rdi
char *const argv[] -> rsi
char *const envp[] -> rdx
E.g.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
const char code[] = "\x48\x31\xc0\x48\xbf\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\x31\xf6\x56\x57\x48\x89\xe7\x48\x31\xd2\xb0\x3b\x0f\x05";
int main(int argc, char **argv)
{
char buf[sizeof(code)];
strcpy(buf, code);
((void(*)( ))buf)( );
}
Compilation and test it.
$ gcc -fno-stack-protector -z execstack shellcode.c -o shellcode
$ ./shellcode
$ uname -a
Linux foobar 4.4.0-97-generic #120-Ubuntu SMP Tue Sep 19 17:28:18 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
code doesn't have a trailing null byte, so you can't use strcpy() to copy it. Use memcpy().
memcpy(buf, code, sizeof(code));
As mentioned in a comment, the shellcode you have is for 32-bit Linux, but you're trying to run it on a 64-bit system. That probably explains the error after fixing this.
You forget the -m32 flag for compiling a 32-bit binary on a 64-bit system. It looks like this is what you need:
gcc -m32 -z execstack -o call_shellcode call_shellcode.c
In order to be able to compile 32-bit binaries on a 64-bit system you need the 32-bit libraries available. On Ubuntu based systems you can install them via:
sudo apt-get install gcc-multilib
See: https://www.homeworkforyou.com/static_media/uploadedfiles/bufoverflow.pdf
As part of an experiment using custom stacks, I wanted a function to return the address of a stack allocated char buffer.
// return pointer to stack variable
void *foo(void)
{
char sz[10] = "hello";
return sz;
}
I know that it's illegal to do this in C, and gcc warns too.
gcc -Wall -Wextra -pedantic -std=gnu99 -fomit-frame-pointer -O0 -c foo.c
foo.c:8:12: warning: function returns address of local variable [-Wreturn-local-addr]
return sz;
Still, since this is part of an experiment, I want the code as is. The funny thing is that the generated code returns 0 instead of sz's stack address:
boa#localhost:~/tmp$ objdump -dMintel foo.o
0000000000000000 <foo>:
0: 48 b8 68 65 6c 6c 6f movabs rax,0x6f6c6c6568
7: 00 00 00
a: 48 89 44 24 f0 mov QWORD PTR [rsp-0x10],rax
f: 66 c7 44 24 f8 00 00 mov WORD PTR [rsp-0x8],0x0
16: b8 00 00 00 00 mov eax,0x0
1b: c3 ret
As one can see, 0x0 is moved to eax, which is what puzzles me. Why does gcc do this?
Here's a complete source file with another function, bar(), as well as a main function. bar() returns the address as expected.
#include <stdint.h>
#include <stdio.h>
// return pointer to stack variable
void *foo(void)
{
char sz[10] = "hello";
return sz;
}
void *bar(void)
{
char sz[10] = "hello";
intptr_t i = (intptr_t)sz;
return (void*)i;
}
int main(void)
{
printf("foo: %p\n", foo());
printf("bar: %p\n", bar());
return 0;
}
boa#localhost:~/tmp$ make foo && ./foo
cc foo.o -o foo
foo: (nil)
bar: 0x7ffce518a268
This is a mystery to me. What may be the logic behind gcc's choice?
GCC deliberately returns NULL in this case as can be seen from the code:
tree zero = build_zero_cst (TREE_TYPE (val));
gimple_return_set_retval (return_stmt, zero);
update_stmt (stmt);
Newer versions of GCC and Clang exploit undefined behavior more aggressively so this check is not suprising. It also makes code fail fast which is a good thing in most cases (not yours, apparently).
I have a plain C program. I have made an executable of it. If I read an elf file, it says me that the entry point is Entry point address: 0x80482e0. After tracking the entry point, I see that the final call is the following.
080482b0 <__gmon_start__#plt-0x10>:
80482b0: ff 35 50 96 04 08 pushl 0x8049650
80482b6: ff 25 54 96 04 08 jmp *0x8049654
80482bc: 00 00 add %al,(%eax)
How can I hack the value of 0x8049654 to call some other function rather than main? I believe the main function address will be stored at the address - 0x8049654? Am I correct? What I want to do is that instead of calling main(), I want to hack it to call some other function? Is it possible?
Is the main function address should be contained in the *0x8049654 ?
main is not called from __gmon_start__:
(gdb) disassemble main
Dump of assembler code for function main:
0x080483d8 <main+0>: push %ebp // main() address
0x080483d9 <main+1>: mov %esp,%ebp
0x080483db <main+3>: and $0xfffffff0,%esp
0x080483de <main+6>: sub $0x10,%esp
0x080483e1 <main+9>: movl $0x80484c9,(%esp)
0x080483e8 <main+16>: call 0x80482f8 <puts#plt>
0x080483ed <main+21>: mov $0x0,%eax
0x080483f2 <main+26>: leave
0x080483f3 <main+27>: ret
End of assembler dump.
(gdb) disassemble __gmon_start__
Dump of assembler code for function __gmon_start__#plt:
0x080482d8 <__gmon_start__#plt+0>: jmp *0x80495c8
0x080482de <__gmon_start__#plt+6>: push $0x0
0x080482e3 <__gmon_start__#plt+11>: jmp 0x80482c8
End of assembler dump.
(gdb) # no call to main
it's got passed from the function _start:
(gdb) disassemble _start
Dump of assembler code for function _start:
0x08048310 <_start+0>: xor %ebp,%ebp
0x08048312 <_start+2>: pop %esi
0x08048313 <_start+3>: mov %esp,%ecx
0x08048315 <_start+5>: and $0xfffffff0,%esp
0x08048318 <_start+8>: push %eax
0x08048319 <_start+9>: push %esp
0x0804831a <_start+10>: push %edx
0x0804831b <_start+11>: push $0x8048400
0x08048320 <_start+16>: push $0x8048410
0x08048325 <_start+21>: push %ecx
0x08048326 <_start+22>: push %esi
0x08048327 <_start+23>: push $0x80483d8
0x0804832c <_start+28>: call 0x80482e8 <__libc_start_main#plt>
0x08048331 <_start+33>: hlt
0x08048332 <_start+34>: nop
...
You can read the ELF header and you will find the address of _start stored in e_entry:
e_entry This member gives the virtual address to which the system
first transfers control, thus starting the process. If
the file has no associated entry point, this member holds
zero.
Here a simple program to get the address:
#include <stdio.h>
#include <elf.h>
int main(int argc, char **argv) {
FILE *file;
Elf32_Ehdr hdr;
if( argc < 2 ) {
printf("uage: %s [FILE]\n", argv[0]);
return -1;
}
if( (file = fopen(argv[1], "r")) == NULL ) {
perror("Error");
return -1;
}
fread(&hdr, sizeof(Elf32_Ehdr), 1, file);
fclose(file);
if( (hdr.e_ident[EI_MAG0] != ELFMAG0) ||
(hdr.e_ident[EI_MAG1] != ELFMAG1) ||
(hdr.e_ident[EI_MAG2] != ELFMAG2) ||
(hdr.e_ident[EI_MAG3] != ELFMAG3) ) {
printf("Error: Error: Not a valid ELF file.\n");
return -1;
}
printf("Entry: 0x%.8x\n", hdr.e_entry);
return 0;
}
So if you want to redirect main to other function, you need to patch this part:
0x08048327 <_start+23>: push $0x80483d8
and replace it with your function. Here I have a simple program:
#include <stdio.h>
void function(void) {
puts("Function");
}
int main(int argc, char **argv) {
puts("Main");
return 0;
}
Will print:
$ ./prog1
Main
$
We need to figure out the address of main and function, using readelf:
$ readelf -s prog1
Symbol table '.dynsym' contains 5 entries:
...
Symbol table '.symtab' contains 66 entries:
Num: Value Size Type Bind Vis Ndx Name
...
61: 080483c4 20 FUNC GLOBAL DEFAULT 14 function
...
64: 080483d8 28 FUNC GLOBAL DEFAULT 14 main
...
$
now patch that push $0x80483d8 and replace the address of main = 080483d8 with function = 080483c4, I used a hex editor, don't forgot to flip the bytes in revere order. It will become:
0x08048327 <_start+23>: push $0x80483c4
now test it:
$ ./prog1
Function
$
Reference: How main() is executed on Linux
That was a quick and dirty way of doing it. If you just want to call something before main is called, you can make function a constructor using GCC attribute __attribute__((constructor)) like this:
#include <stdio.h>
__attribute__((constructor)) void function(void) {
puts("Function");
}
int main(int argc, char **argv) {
puts("Main");
return 0;
}
Now it will be called before main:
$ gcc -Wall prog.c -o prog
$ ./prog
Function
Main
$
Reference: Declaring Attributes of Functions
The entry point as described in your Elf file is not your main() function. main() is first as far as the C language is concerned, but the operating system has other needs (depending on the OS and the compiler). For GCC for example, your initial entry point is likely coming from assembly code in crt0.o; this code handles whatever basic initialization is required and then calls main().
While it's possible to perform a binary edit, it's certainly not trivial and assuming you have source to the code, it's highly questionable as to what benefit you would have in doing so.
following this instructions I have managed to produce only 528 bytes in size a.out (when gcc main.c gave me 8539 bytes big file initially).
main.c was:
int main(int argc, char** argv) {
return 42;
}
but I have built a.out from this assembly file instead:
main.s:
; tiny.asm
BITS 64
GLOBAL _start
SECTION .text
_start:
mov eax, 1
mov ebx, 42
int 0x80
with:
me#comp# nasm -f elf64 tiny.s
me#comp# gcc -Wall -s -nostartfiles -nostdlib tiny.o
me#comp# ./a.out ; echo $?
42
me#comp# wc -c a.out
528 a.out
because I need machine code I do:
objdump -d a.out
a.out: file format elf64-x86-64
Disassembly of section .text:
00000000004000e0 <.text>:
4000e0: b8 01 00 00 00 mov $0x1,%eax
4000e5: bb 2a 00 00 00 mov $0x2a,%ebx
4000ea: cd 80 int $0x80
># objdump -hrt a.out
a.out: file format elf64-x86-64
Sections:
Idx Name Size VMA LMA File off Algn
0 .note.gnu.build-id 00000024 00000000004000b0 00000000004000b0 000000b0 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .text 0000000c 00000000004000e0 00000000004000e0 000000e0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
SYMBOL TABLE:
no symbols
file is in little endian convention:
me#comp# readelf -a a.out
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x4000e0
Start of program headers: 64 (bytes into file)
Start of section headers: 272 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 2
Size of section headers: 64 (bytes)
Number of section headers: 4
Section header string table index: 3
now I want to execute this like this:
#include <unistd.h>
// which version is (more) correct?
// this might be related to endiannes (???)
char code[] = "\x01\xb8\x00\x00\xbb\x00\x00\x2a\x00\x00\x80\xcd\x00";
char code_v1[] = "\xb8\x01\x00\x00\x00\xbb\x2a\x00\x00\x00\xcd\x80\x00";
int main(int argc, char **argv)
{
/*creating a function pointer*/
int (*func)();
func = (int (*)()) code;
(int)(*func)();
return 0;
}
however I get segmentation fault. My question is: is this section of text
4000e0: b8 01 00 00 00 mov $0x1,%eax
4000e5: bb 2a 00 00 00 mov $0x2a,%ebx
4000ea: cd 80 int $0x80
(this machine code) all I really need? What I do wrong (endiannes??), maybe I just need to call this in different way since SIGSEGV?
The code must be in a page with execute permission. By default, stack and read-write static data (like non-const globals) are in pages mapped without exec permission, for security reasons.
The simplest way is to compile with gcc -z execstack, which links your program such that stack and global variables (static storage) get mapped in executable pages, and so do allocations with malloc.
Another way to do it without making everything executable is to copy this binary machine code into an executable buffer.
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
char code[] = {0x55,0x48,0x89,0xe5,0x89,0x7d,0xfc,0x48,
0x89,0x75,0xf0,0xb8,0x2a,0x00,0x00,0x00,0xc9,0xc3,0x00};
/*
00000000004004b4 <main> 55 push %rbp
00000000004004b5 <main+0x1> 48 89 e5 mov %rsp,%rbp
00000000004004b8 <main+0x4> 89 7d fc mov %edi,-0x4(%rbp)
00000000004004bb <main+0x7> 48 89 75 f0 mov %rsi,-0x10(%rbp)
'return 42;'
00000000004004bf <main+0xb> b8 2a 00 00 00 mov $0x2a,%eax
'}'
00000000004004c4 <main+0x10> c9 leaveq
00000000004004c5 <main+0x11> c3 retq
*/
int main(int argc, char **argv) {
void *buf;
/* copy code to executable buffer */
buf = mmap (0,sizeof(code),PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANON,-1,0);
memcpy (buf, code, sizeof(code));
__builtin___clear_cache(buf, buf+sizeof(code)-1); // on x86 this just stops memcpy from optimizing away as a dead store
/* run code */
int i = ((int (*) (void))buf)();
printf("get this done. returned: %d", i);
return 0;
}
output:
get this done. returned: 42
RUN SUCCESSFUL (total time: 57ms)
Without __builtin___clear_cache, this could break with optimization enabled because gcc would think the memcpy was a dead store and optimize it away. When compiling for x86, __builtin___clear_cache does not actually clear any cache; there are zero extra instructions; it just marks the memory as "used" so stores to it aren't considered "dead". (See the gcc manual.)
Another option would be to mprotect the page containing the char code[] array, giving it PROT_READ|PROT_WRITE|PROT_EXEC. This works whether it's a local array (on the stack) or global in the .data.
Or if it's const char code[] in the .rodata section, you might just give it PROT_READ|PROT_EXEC.
(In versions of binutils ld from before about 2019, the .rodata got linked as part of the same segment as .text, and was already mapped executable. But recent ld gives it a separate segment so it can be mapped without exec permission so const char code[] doesn't give you an executable array anymore, but it used to so you may this old advice in other places.)
The point is that DEP protection is enabled!
you can goto Configurations -> Linker -> Advance -> DEP turn off ,
it's ok now .
void main(){
int i = 11;
//The following is the method to generate the machine code directly!
//mov eax, 1; ret;
const char *code = "\xB8\x10\x00\x00\x00\xc3";
__asm call code; //test successful~..vs 2017
__asm mov i ,eax;
printf("i=%d", i);
}
This question already has answers here:
How to call machine code stored in char array?
(6 answers)
Closed 6 years ago.
I get a segmentation fault when I run the following C program (compiled with gcc in Ubuntu).
#include <stdio.h>
char f[] = "\x55\x48\x89\xe5\x48\x89\x7d\xf8\x48\x89\x75\xf0\x48\x8b\x45\xf8\x8b\x10\x48\x8b\x45\xf0\x8b\x00\x89\xd1\x29\xc1\x89\xc8\xc9\xc3";
int main()
{
int (*func)();
func = (int (*)()) f;
int x=3,y=5;
printf("%d\n",(int)(*func)(&x,&y));
return 0;
}
The string f contains the machine code of the following function.
int f(int*a, int*b)
{
return *a-*b;
}
c.f.:
f.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <f>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 89 7d f8 mov %rdi,-0x8(%rbp)
8: 48 89 75 f0 mov %rsi,-0x10(%rbp)
c: 48 8b 45 f8 mov -0x8(%rbp),%rax
10: 8b 10 mov (%rax),%edx
12: 48 8b 45 f0 mov -0x10(%rbp),%rax
16: 8b 00 mov (%rax),%eax
18: 89 d1 mov %edx,%ecx
1a: 29 c1 sub %eax,%ecx
1c: 89 c8 mov %ecx,%eax
1e: c9 leaveq
1f: c3 retq
This is compiled using:
gcc test.c -Wall -Werror
./a.out
Segmentation fault
The expected output is -2 - how can I get it to work?
Apparantly below suggestion no longer works with gcc, as the array data nowadays gets located in a separate non-executable read-only ELF segment.
I'll leave it here for historical reasons.
Interestingly, the linker didn't complain that you attempt to link a char f[] = "..."; as a function f() to your application. You attempt to call a function f(). There is a symbol f linked to the executable, but suprisingly it is no function at all, but some variable. And thus it fails to execute it. This is likely due to a stack execution protection mechanism.
To circumvent this, apparantly, you just need to get the string to the text segment of the process memory. You can achieve this, if you declare the string as const char f[].
From Smashing The Stack For Fun And Profit, by Aleph One:
The text region is fixed by the program and includes code (instructions)
and read-only data. This region corresponds to the text section of the
executable file.
As the const char[] is read-only, the compiler puts it together with the code into the text region. Thereby the execution prevention mechanism is circumvented and the machine is able to execute the machine code therein.
Example:
/* test.c */
#include <stdio.h>
const char f[] = "\x55\x48\x89\xe5\x48\x89\x7d\xf8\x48\x89\x75\xf0\x48\x8b\x45\xf8\x8b\x10\x48\x8b\x45\xf0\x8b\x00\x89\xd1\x29\xc1\x89\xc8\xc9\xc3";
int main()
{
int (*func)();
func = (int (*)()) f;
int x=3,y=5;
printf("%d\n",(int)(*func)(&x,&y));
return 0;
}
yields:
$ gcc test.c -Wall && ./a.out
-2
(Fedora 16, gcc 4.6.3)
If I understand you correctly you're trying to run simple code that is not in text space, but instead is in your initialized static storage? If this is failing then there can only be three reasons: either your code was initialized incorrectly (unlikely in this simple case), your data space has been stepped on (doesn't look like it in this simple case), or your system is preventing it as a security measure (quite likely since what you're trying to do is fairly atypical, primarily used for buffer overflow exploitation).