shellcode buffer overflow -SegFault - c

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

Related

How to run a mixed language program

I want to write a mixed language program where part of the code will be written in C, and part of the code in assembly. I was given a sample code, so i know what should my work look like.
.globl _addArrayinA
_addArrayinA:
pushl %ebp
movl %esp,%ebp
subl $8,%esp
movl 8(%ebp), %ebx
xorl %esi,%esi
xor %eax,%eax
bak:
addl (%ebx),%eax
addl $4,%ebx
incl %esi
cmpl $10, %esi
jne bak
movl %ebp, %esp
popl %ebp
ret
# Return value is in %ea
Above is the assembly part.
int addArrayinC(int *myArray, int num)
{
int c;
int i;
c = 0;
for (i=0; i<num; i++)
{c += *myArray;
myArray++;
}
return (c);
}
This is the second function written in C.
And below is the main file, which is supposed to use two functions above.
#include <stdio.h>
#include <stdlib.h>
extern int addArrayinC(int *numbers,int count);
extern int addArrayinA(int *numbers, int count);
int main(void) {
int mynumbers[10]={1,2,3,4,5,6,7,8,9,0};
int sum;
sum = addArrayinC(mynumbers, 10);
printf("\nThe sum of array computed in C is : %d ",sum);
sum = addArrayinA(mynumbers, 10);
printf("\nThe sum of array computed in assembly is : %d ",sum);
return EXIT_SUCCESS;
}
I tried to open these three files in codeblocks, but could not get to run them. I have no idea how to run a mixed language program. Generally, I use cloud9 for compilations of code. Anyways... How can i run code like this?
No problem here. Please note: the extension of the assembler source file has to be .s or .S(upper case if you want the file to be preprocessed e.g. for #define).
fun.c
unsigned int fun ( unsigned int x )
{
return(x+1);
}
build and examine
gcc -c -O2 fun.c -o fun.o
objdump -D fun.o
producing
0000000000000000 <fun>:
0: 8d 47 01 lea 0x1(%rdi),%eax
3: c3 retq
So we can make fun.s
.globl fun
fun:
lea 0x1(%rdi),%eax
retq
as fun.s -o fun.o
objdump -D fun.o
0000000000000000 <fun>:
0: 8d 47 01 lea 0x1(%rdi),%eax
3: c3 retq
C code so.c
#include <stdio.h>
unsigned int fun ( unsigned int x );
int main ( void )
{
printf("%u\n",fun(1));
printf("%u\n",fun(2));
printf("%u\n",fun(3));
return(0);
}
gcc lets you feed it assembly language
gcc so.c fun.s -o so
./so
2
3
4
as well as objects
gcc so.c fun.o
./so
2
3
4
so you dont have to mess with the linker directly

Desiging Shellcode gives incorrect results

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

Program compiled with -fPIC crashes while stepping over thread-local variable in GDB

This is a very strange problem which occurs only when the program is compiled with -fPIC option.
Using gdb I'm able to print thread local variables but stepping over them leads to crash.
thread.c
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#define MAX_NUMBER_OF_THREADS 2
struct mystruct {
int x;
int y;
};
__thread struct mystruct obj;
void* threadMain(void *args) {
obj.x = 1;
obj.y = 2;
printf("obj.x = %d\n", obj.x);
printf("obj.y = %d\n", obj.y);
return NULL;
}
int main(int argc, char *arg[]) {
pthread_t tid[MAX_NUMBER_OF_THREADS];
int i = 0;
for(i = 0; i < MAX_NUMBER_OF_THREADS; i++) {
pthread_create(&tid[i], NULL, threadMain, NULL);
}
for(i = 0; i < MAX_NUMBER_OF_THREADS; i++) {
pthread_join(tid[i], NULL);
}
return 0;
}
Compile it using the following: gcc -g -lpthread thread.c -o thread -fPIC
Then while debugging it: gdb ./thread
(gdb) b threadMain
Breakpoint 1 at 0x4006a5: file thread.c, line 15.
(gdb) r
Starting program: /junk/test/thread
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
[New Thread 0x7ffff7fc7700 (LWP 31297)]
[Switching to Thread 0x7ffff7fc7700 (LWP 31297)]
Breakpoint 1, threadMain (args=0x0) at thread.c:15
15 obj.x = 1;
(gdb) p obj.x
$1 = 0
(gdb) n
Program received signal SIGSEGV, Segmentation fault.
threadMain (args=0x0) at thread.c:15
15 obj.x = 1;
Although, if I compile it without -fPIC then this problem doesn't occur.
Before anybody asks me why am I using -fPIC, this is just a reduced test case. We have a huge component which compiles into a so file which then plugs into another component. Therefore, fPIC is necessary.
There is no functional impact because of it, only that debugging is near impossible.
Platform Information: Linux 2.6.32-431.el6.x86_64 #1 SMP Sun Nov 10 22:19:54 EST 2013 x86_64 x86_64 x86_64 GNU/Linux, Red Hat Enterprise Linux Server release 6.5 (Santiago)
Reproducible on the following as well
Linux 3.13.0-66-generic #108-Ubuntu SMP Wed Oct 7 15:20:27
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
The problem lies deep in the bowels of GAS, the GNU assembler, and how it generates DWARF debug information.
The compiler, GCC, has the responsibility of generating a specific sequence of instructions for a position-independent thread-local access, which is documented in the document ELF Handling for Thread-Local Storage, page 22, section 4.1.6: x86-64 General Dynamic TLS Model. This sequence is:
0x00 .byte 0x66
0x01 leaq x#tlsgd(%rip),%rdi
0x08 .word 0x6666
0x0a rex64
0x0b call __tls_get_addr#plt
, and is the way it is because the 16 bytes it occupies leave space for backend/assembler/linker optimizations. Indeed, your compiler generates the following assembler for threadMain():
threadMain:
.LFB2:
.file 1 "thread.c"
.loc 1 14 0
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movq %rdi, -8(%rbp)
.loc 1 15 0
.byte 0x66
leaq obj#tlsgd(%rip), %rdi
.value 0x6666
rex64
call __tls_get_addr#PLT
movl $1, (%rax)
.loc 1 16 0
...
The assembler, GAS, then relaxes this code, which contains a function call (!), down to just two instructions. These are:
a mov having an fs:-segment override, and
a lea
, in the final assembly. They occupy between themselves 16 bytes in total, demonstrating why the General Dynamic Model instruction sequence is designed to require 16 bytes.
(gdb) disas/r threadMain
Dump of assembler code for function threadMain:
0x00000000004007f0 <+0>: 55 push %rbp
0x00000000004007f1 <+1>: 48 89 e5 mov %rsp,%rbp
0x00000000004007f4 <+4>: 48 83 ec 10 sub $0x10,%rsp
0x00000000004007f8 <+8>: 48 89 7d f8 mov %rdi,-0x8(%rbp)
0x00000000004007fc <+12>: 64 48 8b 04 25 00 00 00 00 mov %fs:0x0,%rax
0x0000000000400805 <+21>: 48 8d 80 f8 ff ff ff lea -0x8(%rax),%rax
0x000000000040080c <+28>: c7 00 01 00 00 00 movl $0x1,(%rax)
So far, everything has been done correctly. The problem now begins as GAS generates DWARF debug information for your particular assembler code.
While parsing line-by-line in binutils-x.y.z/gas/read.c, function void
read_a_source_file (char *name), GAS encounters .loc 1 15 0, the statement that begins the next line, and runs the handler void dwarf2_directive_loc (int dummy ATTRIBUTE_UNUSED) in dwarf2dbg.c. Unfortunately, the handler does not unconditionally emit debug information for the current offset within the "fragment" (frag_now) of machine code it is currently building. It could have done this by calling dwarf2_emit_insn(0), but the .loc handler currently only does so if it sees multiple .loc directives consecutively. Instead, in our case it continues on to the next line, leaving the debug information unemitted.
On the next line it sees the .byte 0x66 directive of the General Dynamic sequence. This is not, in and of itself, part of an instruction, despite representing the data16 instruction prefix in x86 assembly. GAS acts upon it with the handler cons_worker(), and the fragment increases from 12 bytes to 13 in size.
On the next line it sees a true instruction, leaq, which is parsed by calling the macro assemble_one() that maps to void md_assemble (char *line) in gas/config/tc-i386.c. At the very end of that function, output_insn() is called, which itself finally calls dwarf2_emit_insn(0) and causes debug information to be emitted at last. A new Line Number Statement (LNS) is begun that claims that line 15 began at function-start-address plus previous fragment size, but since we passed over the .byte statement before doing so, the fragment is 1 byte too large, and the computed offset for the first instruction of line 15 is therefore 1 byte off.
Some time later GAS relaxes the Global Dynamic Sequence to the final instruction sequence that starts with mov fs:0x0, %rax. The code size and all offsets remain unchanged because both sequences of instructions are 16 bytes. The debug information is unchanged, and still wrong.
GDB, when it reads the Line Number Statements, is told that the prologue of threadMain(), which is associated with the line 14 on which is found its signature, ends where line 15 begins. GDB dutifully plants a breakpoint at that location, but unfortunately it is 1 byte too far.
When run without a breakpoint, the program runs normally, and sees
64 48 8b 04 25 00 00 00 00 mov %fs:0x0,%rax
. Correctly placing the breakpoint would involve saving and replacing the first byte of an instruction with int3 (opcode 0xcc), leaving
cc int3
48 8b 04 25 00 00 00 00 mov (0x0),%rax
. The normal step-over sequence would then involve restoring the first byte of the instruction, setting the program counter eip to the address of that breakpoint, single-stepping, re-inserting the breakpoint, then continuing the program.
However, when GDB plants the breakpoint at the incorrect address 1 byte too far, the program sees instead
64 cc fs:int3
8b 04 25 00 00 00 00 <garbage>
which is a wierd but still valid breakpoint. That's why you didn't see SIGILL (illegal instruction).
Now, when GDB attempts to step over, it restores the instruction byte, sets the PC to the address of the breakpoint, and this is what it sees now:
64 fs: # CPU DOESN'T SEE THIS!
48 8b 04 25 00 00 00 00 mov (0x0),%rax # <- CPU EXECUTES STARTING HERE!
# BOOM! SEGFAULT!
Because GDB restarted execution one byte too far, the CPU does not decode the fs: instruction prefix byte, and instead executes mov (0x0),%rax with the default segment, which is ds: (data). This immediately results in a read from address 0, the null pointer. The SIGSEGV promptly follows.
All due credits to Mark Plotnick for essentially nailing this.
The solution that was retained is to binary-patch cc1, gcc's actual C compiler, to emit data16 instead of .byte 0x66. This results in GAS parsing the prefix and instruction combination as a single unit, yielding the correct offset in the debug information.

How to hack an elf file to call other function() rather main?

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.

execute binary machine code from C

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);
}

Resources