🟤Cross-compiling Binaries
Compiling exploits for windows on Linux can be a bit of a hassle. It depends on OS (windows, linux,...) and the architecture (x86, x64). Compiling executable on one OS/arch to be used on different one is called cross-compiling. Thanks to diingus, i'll cover here all four most common cross-compile combination. I assume that you're using gcc with all dependencies preinstalled.
Windows
x86
x86 means 32 bit architecture
i686-w64-mingw32-gcc exploit.c -o exploit_32.exe
In case when code uses/includes winsock 2
i686-w64-mingw32-gcc exploit.c -oexploit_x86.exe -lws2_32
x64
x64 means 64 bit architecture. Sometimes also refered as amd64.
x86_64-w64-mingw32-gcc exploit.c -o exploit_64.exe
Linux
x86
gcc exploit.c -o exploit_x86 -m32
-m32 is optional if host architecture is x32
x64
gcc exploit.c -o exploit_x64 -m64
target specific
gcc exploit.c -o exploit_x64 -m64 -Wl,--hash-style=both
--hash-style=both
Depending on how your distro's GCC was configured, hash tables can be different. AFAIK most use either both or gnu styles by default. Both simply means that linked files will include, both gnu and sysv hashtables. This shouldn't matter unless you try to run your program on a system with dynamic linker which does not understand GNU hashtables. In that case, if program was built with -Wl,--hash-style=gnu, you'll get an error at startup about unsupported hashtable format.
compiling dynamic/static libraries
If you need to build a library and link it to the program, this is the way to go.
NOTE: all different build types from above are applicable here as well (win/lin, x86/x64)
These are the files used in all examples, so you can repeat everything by copy/paste commands.
library.h
#pragma once // this is to ensure that this h file (library.h) is only included once, even if it is mentioned in multiple places
#include <stdio.h>
void my_print(int a);
library.c
#include "library.h"
void my_print(int a)
{
printf("my_print: %d\n", a);
}
program.c
#include "library.h"
void main()
{
int n = 10;
my_print(n);
}
Build a dynamically linkable library (so)
gcc -shared -fpic library.c -o library.so
Check the output file
file library.so
library.so: ELF 32-bit LSB pie executable Intel 80386, version 1 (SYSV), dynamically linked, BuildID[sha1]=eae3bc2e3a5be284d1dd8d13bd047edb98330d30, not stripped
nm library.so
00004014 b completed.6950
w __cxa_finalize@@GLIBC_2.1.3
00001070 t deregister_tm_clones
00001100 t __do_global_dtors_aux
00003f0c t __do_global_dtors_aux_fini_array_entry
00004010 d __dso_handle
00003f10 d _DYNAMIC
0000118c T _fini
00001150 t frame_dummy
00003f08 t __frame_dummy_init_array_entry
000020c4 r __FRAME_END__
00004000 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
00002010 r __GNU_EH_FRAME_HDR
00001000 T _init
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
00001159 T my_print // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
U printf@@GLIBC_2.0
000010b0 t register_tm_clones
00004014 d __TMC_END__
00001187 t __x86.get_pc_thunk.ax
00001060 t __x86.get_pc_thunk.bx
00001155 t __x86.get_pc_thunk.dx
ldd library.so
linux-gate.so.1 (0xb7fba000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7db5000)
/lib/ld-linux.so.2 (0xb7fbc000)
Compile and link the program, using previously built library
gcc -L./ -lrary program.c -o program
NOTE: -lrary means library; 'lib' will be added by the compiler, so if you want to link something called 'library', you need to remove 'lib' part coz it will be added automatically.
Check the output file
file program
program: ELF 32-bit LSB pie executable Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=fb84b93b5662e24e8021111bca1a11bc8fcdc45a, not stripped
ldd program
linux-gate.so.1 (0xb7fbf000)
library.so => not found
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7dba000)
/lib/ld-linux.so.2 (0xb7fc1000)
NOTE: in case of an error (like shown above), it means that loader doesn't know how to find library.so (the fact that it is in the same folder as program wasn't enough for loader to find it). The loader searches for libraries based on environment variable LD_LIBRARY_PATH; so, if you want to use the library.so (or any other missing library), you need to either add the folder which contains the missing to LD_LIBRARY_PATH, or to copy library.so to the place where other libraries (so files) reside.
WORKAROUND
In some cases you can link statically by compiling static library (.a) and then compile the program using and including that static library. That means that the library itself will be included in the final program. That may not work in some cases + it increases size of the final file. The example follows:
Compile to an object file
gcc -c library.c -o library.o
Make an archive out of it
ar rcs library.a library.o
Check the output files
file library.o
library.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
file library.a
library.a: current ar archive
compile with static libs
gcc -static program.c -L. -lrary -o program
IMPORTANT: the order of the arguments is VERY IMPORTANT; if you make a change in order, build will fail !!!
Check the output file
file program
program: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=50ef66baa532078ccf1df75e3a82a1304b834110, not stripped
ldd program
not a dynamic executable
'not a dynamic executable' - means that we did what we wanted - no dynamic executable was required, which means that everything app needs is already inside the executable.
_GNU_SOURCE macro
Sometimes, you will have to use additional functionalities in C which are not provided by standard C. In that case, you need to use additional functionalities, which can be turn on by macro _GNU_SOURCE.
From manual:
_GNU_SOURCE
Defining this macro (with any value) implicitly defines _ATFILE_SOURCE, _LARGEFILE64_SOURCE, _ISOC99_SOURCE, _XOPEN_SOURCE_EXTENDED, _POSIX_SOURCE, _POSIX_C_SOURCE with the value 200809L (200112L in glibc versions before 2.10; 199506L in glibc versions before 2.5; 199309L in glibc ver‐ sions before 2.1) and _XOPEN_SOURCE with the value 700 (600 in glibc versions before 2.10; 500 in glibc versions before 2.2). In addition, various GNU-specific extensions are also exposed.
Since glibc 2.19, defining _GNU_SOURCE also has the effect of implicitly defining _DEFAULT_SOURCE. In glibc versions before 2.20, defining _GNU_SOURCE also had the effect of implicitly defining _BSD_SOURCE and _SVID_SOURCE.
Note: _GNU_SOURCE needs to be defined before including header files so that the respective headers enable the features. For example:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
...
_GNU_SOURCE can be also be enabled per compilation using -D flag:
$ gcc -D _GNU_SOURCE file.c
(-D is not specific to _GNU_SOURCE but any macro be defined this way).
Last updated