💾 Archived View for radare.org › book › tools › ragg2 › ragg2.gmi captured on 2024-05-10 at 11:12:46. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-11-04)

➡️ Next capture (2024-08-18)

-=-=-=-=-=-=-

ragg2

ragg2 stands for `radare2 egg`, this is the basic block to construct relocatable snippets of code to be used for injection in target processes when doing exploiting.

ragg2 compiles programs written in a simple high-level language into tiny binaries for x86, x86-64, and ARM.

By default it will compile it's own `ragg2` language, but you can also compile C code using GCC or Clang shellcodes depending on the file extension. Lets create C file called `a.c`:

int main() {
	write(1, "Hello World\n", 13);
	return 0;
}
$ ragg2 -a x86 -b32 a.c
e900000000488d3516000000bf01000000b80400000248c7c20d0000000f0531c0c348656c6c6f20576f726c640a00

$ rasm2 -a x86 -b 32 -D e900000000488d3516000000bf01000000b80400000248c7c20d0000000f0531c0c348656c6c6f20576f726c640a00
0x00000000   5               e900000000  jmp 5
0x00000005   1                       48  dec eax
0x00000006   6             8d3516000000  lea esi, [0x16]
0x0000000c   5               bf01000000  mov edi, 1
0x00000011   5               b804000002  mov eax, 0x2000004
0x00000016   1                       48  dec eax
0x00000017   6             c7c20d000000  mov edx, 0xd
0x0000001d   2                     0f05  syscall
0x0000001f   2                     31c0  xor eax, eax
0x00000021   1                       c3  ret
0x00000022   1                       48  dec eax
0x00000023   2                     656c  insb byte es:[edi], dx
0x00000025   1                       6c  insb byte es:[edi], dx
0x00000026   1                       6f  outsd dx, dword [esi]
0x00000027   3                   20576f  and byte [edi + 0x6f], dl
0x0000002a   2                     726c  jb 0x98
0x0000002c   3                   640a00  or al, byte fs:[eax]

Compiling ragg2 example

$ cat hello.r
exit@syscall(1);

main@global() {
	exit(2);
}

$ ragg2 -a x86 -b 64 hello.r
48c7c00200000050488b3c2448c7c0010000000f054883c408c3
0x00000000   1                       48  dec eax
0x00000001   6             c7c002000000  mov eax, 2
0x00000007   1                       50  push eax
0x00000008   1                       48  dec eax
0x00000009   3                   8b3c24  mov edi, dword [esp]
0x0000000c   1                       48  dec eax
0x0000000d   6             c7c001000000  mov eax, 1
0x00000013   2                     0f05  syscall
0x00000015   1                       48  dec eax
0x00000016   3                   83c408  add esp, 8
0x00000019   1                       c3  ret

$ rasm2 -a x86 -b 64 -D 48c7c00200000050488b3c2448c7c0010000000f054883c408c3
0x00000000   7           48c7c002000000  mov rax, 2
0x00000007   1                       50  push rax
0x00000008   4                 488b3c24  mov rdi, qword [rsp]
0x0000000c   7           48c7c001000000  mov rax, 1
0x00000013   2                     0f05  syscall
0x00000015   4                 4883c408  add rsp, 8
0x00000019   1                       c3  ret

Injectable machine code in different forms

Consider the following program:

$ cat code1.c
int main()
{
	write(1, "Hello World\n", 13);
	exit(0);
}

One can get raw machine code of the above program like this:

$ ragg2 code1.c
eb0e66666666662e0f1f84000000000050bf01000000488d359f000000ba0d000000e81900000031ff89442404e85e00000031d289042489d059c30f1f440000897c24fc48897424f0895424ec8b5424fc895424dc488b7424f048897424d08b5424ec895424cc8b7c24dc488b7424d08b5424ccb8010000000f0548894424e0488b4424e089c1894c24c88b4424c8c3897c24fc8b7c24fc897c24ec8b7c24ecb83c0000000f0548894424f0488b4424f089c1894c24e88b4424e8c348656c6c6f20576f726c640a00

If you want it in a file, you may use the '-O' flag which uses the default filename or you may specify the output filename using '-o' option.

$ ragg2 -O code1.c
$ cat code1
eb0e66666666662e0f1f84000000000050bf01000000488d359f000000ba0d000000e81900000031ff89442404e85e00000031d289042489d059c30f1f440000897c24fc48897424f0895424ec8b5424fc895424dc488b7424f048897424d08b5424ec895424cc8b7c24dc488b7424d08b5424ccb8010000000f0548894424e0488b4424e089c1894c24c88b4424c8c3897c24fc8b7c24fc897c24ec8b7c24ecb83c0000000f0548894424f0488b4424f089c1894c24e88b4424e8c348656c6c6f20576f726c640a00
$ ragg2 -o code1.raw code1.c
$ cat code1.raw
eb0e66666666662e0f1f84000000000050bf01000000488d359f000000ba0d000000e81900000031ff89442404e85e00000031d289042489d059c30f1f440000897c24fc48897424f0895424ec8b5424fc895424dc488b7424f048897424d08b5424ec895424cc8b7c24dc488b7424d08b5424ccb8010000000f0548894424e0488b4424e089c1894c24c88b4424c8c3897c24fc8b7c24fc897c24ec8b7c24ecb83c0000000f0548894424f0488b4424f089c1894c24e88b4424e8c348656c6c6f20576f726c640a00

The above is a basic 'raw' output. ragg2 offers a number of output format options via `-f`. One can find it through ```ragg2 -h``` or ragg2's manpage.


-f format   output format (raw, c, pe, elf, mach0, python, javascript)

The following is 'c' format output - shellcode which can be readily used in your C program.


$ ragg2 -f c -o code1.c.c code1.c $ cat code1.c.c const unsigned char cstr[201] = ""\   "\xeb\x0e\x66\x66\x66\x66\x66\x2e\x0f\x1f\x84\x00\x00\x00\x00\x00\x50\xbf\x01\x00\x00"\   "\x00\x48\x8d\x35\x9f\x00\x00\x00\xba\r\x00\x00\x00\xe8\x19\x00\x00\x00"\   "\x31\xff\x89\x44\x24\x04\xe8\x5e\x00\x00\x00\x31\xd2\x89\x04\x24\x89\xd0\x59\xc3\x0f"\   "\x1f\x44\x00\x00\x89\x7c\x24\xfc\x48\x89\x74\x24\xf0\x89\x54\x24\xec\x8b\x54\x24\xfc\x89\x54\x24\xdc"\   "\x48\x8b\x74\x24\xf0\x48\x89\x74\x24\xd0\x8b\x54\x24\xec\x89\x54\x24\xcc\x8b\x7c\x24\xdc\x48\x8b\x74\x24\xd0"\   "\x8b\x54\x24\xcc\xb8\x01\x00\x00\x00\x0f\x05\x48\x89\x44\x24\xe0\x48\x8b\x44\x24\xe0\x89"\   "\xc1\x89\x4c\x24\xc8\x8b\x44\x24\xc8\xc3\x89\x7c\x24\xfc\x8b\x7c\x24\xfc\x89\x7c\x24\xec\x8b"\   "\x7c\x24\xec\xb8\x3c\x00\x00\x00\x0f\x05\x48\x89\x44\x24\xf0\x48\x8b\x44\x24\xf0\x89\xc1"\   "\x89\x4c\x24\xe8\x8b\x44\x24\xe8\xc3\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\n\x00";

You may readily use it in C programs like this:


$ cat code1.c.c int main() { 	const unsigned char cstr[201] = ""\ 	  "\xeb\x0e\x66\x66\x66\x66\x66\x2e\x0f\x1f\x84\x00\x00\x00\x00\x00\x50\xbf\x01\x00\x00"\ 	  "\x00\x48\x8d\x35\x9f\x00\x00\x00\xba\r\x00\x00\x00\xe8\x19\x00\x00\x00"\ 	  "\x31\xff\x89\x44\x24\x04\xe8\x5e\x00\x00\x00\x31\xd2\x89\x04\x24\x89\xd0\x59\xc3\x0f"\ 	  "\x1f\x44\x00\x00\x89\x7c\x24\xfc\x48\x89\x74\x24\xf0\x89\x54\x24\xec\x8b\x54\x24\xfc\x89\x54\x24\xdc"\ 	  "\x48\x8b\x74\x24\xf0\x48\x89\x74\x24\xd0\x8b\x54\x24\xec\x89\x54\x24\xcc\x8b\x7c\x24\xdc\x48\x8b\x74\x24\xd0"\ 	  "\x8b\x54\x24\xcc\xb8\x01\x00\x00\x00\x0f\x05\x48\x89\x44\x24\xe0\x48\x8b\x44\x24\xe0\x89"\ 	  "\xc1\x89\x4c\x24\xc8\x8b\x44\x24\xc8\xc3\x89\x7c\x24\xfc\x8b\x7c\x24\xfc\x89\x7c\x24\xec\x8b"\ 	  "\x7c\x24\xec\xb8\x3c\x00\x00\x00\x0f\x05\x48\x89\x44\x24\xf0\x48\x8b\x44\x24\xf0\x89\xc1"\ 	  "\x89\x4c\x24\xe8\x8b\x44\x24\xe8\xc3\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\n\x00";

void (*func)() = cstr; 	func();

return 0; } ```

Compile and run it.

$ gcc code1.c.c -o code1.c.elf -zexecstack

code1.c.c: In function ‘main’:

code1.c.c:14:19: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]

void (*func)() = cstr;

^~~~

$ ./code1.c.elf

Hello World


Similar to how the above code is readily usable in C programs, ragg2 can emit python-ready and js-ready code too(using the '-f python' and -f javascript' options).

To generate an executable binary for your native architecture, you may use the '-F' option.

$ ragg2 -F -o code1.elf code1.c

$ ./code1.elf

Hello World


You may specify the binary format output.

$ ragg2 -f elf -o code1_f.elf code1.c

$ ./code1_f.elf

Hello World


OR

$ ragg2 -f mach0 -o code1_f.mach0 code1.c

$ file code1_f.mach0

code1_f.mach0: Mach-O 64-bit x86_64 executable


Same with 'pe' format.

In the above examples, the target architecture is the architecture of your machine. But target architecture can explicitly be specified using the '-a' option.

$ ragg2 -f raw -a x86 -b 32 code1.c

eb4e66666666662e0f1f840000000000575683ec108b4424208b4c241c8b54241c8b742420bf66000000894c240889f18944240489f85389d3cd805b8944240c8b44240c8904248b042483c4105e5fc3535683ec24e8000000005881c0661e0000b9010000008d9083e2ffffbe0d000000c704240100000089542404c74424080d00000089c389442420894c241c89742418e82900000031c9c70424000000008b5c242089442414894c2410e86f00000031c083c4245e5bc30f1f80000000005553575683ec148b4424308b4c242c8b5424288b7424288b7c242c8b5c2430bd04000000894c240c89f98954240889da8944240489e85389f3cd805b894424108b4424108904248b042483c4145e5f5b5dc366666666662e0f1f84000000000083ec088b44240c8b4c240cba0100000089042489d05389cbcd805b8944240483c408c348656c6c6f20576f726c640a00


The '-b' option can be used to specify the bits. One can see the supported architectures from ragg2's help or manpage.

-a [arch] select architecture (x86, mips, arm)

-b [bits] register size (32, 64, ..)


The '-r' flag can be used to generate binary output instead of the above hex-string style output.

$ ragg2 -f raw -r code1.c

�1��D$�^1҉$��Y�D�|$�H�t$��T$��T$��T$�H�t$�H�t$ЋT$��T$̋|$�H�t$ЋT$̸H�D$�H�D$����L$ȋD$�É|$��|$��|$��|$��<H�D$�H�D$����L$��D$��Hello World


$ ragg2 -f raw -a x86 -b 64 -r code1.c | xxd

00000000: eb0e 6666 6666 662e 0f1f 8400 0000 0000 ..fffff.........

00000010: 50bf 0100 0000 488d 359f 0000 00ba 0d00 P.....H.5.......

00000020: 0000 e819 0000 0031 ff89 4424 04e8 5e00 .......1..D$..^.

00000030: 0000 31d2 8904 2489 d059 c30f 1f44 0000 ..1...$..Y...D..

00000040: 897c 24fc 4889 7424 f089 5424 ec8b 5424 .|$.H.t$..T$..T$

00000050: fc89 5424 dc48 8b74 24f0 4889 7424 d08b ..T$.H.t$.H.t$..

00000060: 5424 ec89 5424 cc8b 7c24 dc48 8b74 24d0 T$..T$..|$.H.t$.

00000070: 8b54 24cc b801 0000 000f 0548 8944 24e0 .T$........H.D$.

00000080: 488b 4424 e089 c189 4c24 c88b 4424 c8c3 H.D$....L$..D$..

00000090: 897c 24fc 8b7c 24fc 897c 24ec 8b7c 24ec .|$..|$..|$..|$.

000000a0: b83c 0000 000f 0548 8944 24f0 488b 4424 .<.....H.D$.H.D$

000000b0: f089 c189 4c24 e88b 4424 e8c3 4865 6c6c ....L$..D$..Hell

000000c0: 6f20 576f 726c 640a 00 o World..


Using '-z' flag instead of '-r' would generate a C-style hex-string output.

$ ragg2 -f raw -z code1.c

"\xeb\x0e\x66\x66\x66\x66\x66\x2e\x0f\x1f\x84\x00\x00\x00\x00\x00\x50\xbf\x01\x00\x00\x00\x48\x8d\x35\x9f\x00\x00\x00\xba\x0d\x00\x00\x00\xe8\x19\x00\x00\x00\x31\xff\x89\x44\x24\x04\xe8\x5e\x00\x00\x00\x31\xd2\x89\x04\x24\x89\xd0\x59\xc3\x0f\x1f\x44\x00\x00\x89\x7c\x24\xfc\x48\x89\x74\x24\xf0\x89\x54\x24\xec\x8b\x54\x24\xfc\x89\x54\x24\xdc\x48\x8b\x74\x24\xf0\x48\x89\x74\x24\xd0\x8b\x54\x24\xec\x89\x54\x24\xcc\x8b\x7c\x24\xdc\x48\x8b\x74\x24\xd0\x8b\x54\x24\xcc\xb8\x01\x00\x00\x00\x0f\x05\x48\x89\x44\x24\xe0\x48\x8b\x44\x24\xe0\x89\xc1\x89\x4c\x24\xc8\x8b\x44\x24\xc8\xc3\x89\x7c\x24\xfc\x8b\x7c\x24\xfc\x89\x7c\x24\xec\x8b\x7c\x24\xec\xb8\x3c\x00\x00\x00\x0f\x05\x48\x89\x44\x24\xf0\x48\x8b\x44\x24\xf0\x89\xc1\x89\x4c\x24\xe8\x8b\x44\x24\xe8\xc3\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x0a\x00"


Instead of using C, a domain specific language designed for ragg2 can also be used - you may refer to this[1] page.

=> https://book.rada.re/tools/ragg2/lang.html 1: this

The `-e` option can be used if you want to input the code as an argument to ragg2 and not as a file. Note that you can only use ragg2 language here(and not C).

$ ragg2 -e "exit@syscall(60); write@syscall(4); main@global(128) {write(1, \"Hello World\n\", 13); exit(0);}"

554889e54881ec8000000048c7c00d00000050c7452048656c6cc745246f20576fc74528726c640ac7452c00000000c7453000000000488d452048898518000000488b45185048c7c00100000050488b3c24488b742408488b54241048c7c0040000000f054883c41848c7c00000000050488b3c2448c7c03c0000000f054883c4084881c4800000005dc3


Other options like architecture, bits, output file format etc., can be used here too.

$ ragg2 -e "exit@syscall(60); write@syscall(4); main@global(128) {write(1, \"Hello World\n\", 13); exit(0);}" -f elf -o output.elf

$ file output.elf

output.elf: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, corrupted section header size

$ ragg2 -e "exit@syscall(60); write@syscall(4); main@global(128) {write(1, \"Hello World\n\", 13); exit(0);}" -f c

const unsigned char cstr[139] = ""\

"\x55\x48\x89\xe5\x48\x81\xec\x80\x00\x00\x00\x48\xc7\xc0\r\x00\x00\x00\x50\xc7"\

"\x45\x20\x48\x65\x6c\x6c\xc7\x45\x24\x6f\x20\x57\x6f\xc7\x45\x28\x72\x6c\x64\n\xc7\x45\x2c\x00\x00\x00\x00\xc7\x45\x30\x00\x00"\

"\x00\x00\x48\x8d\x45\x20\x48\x89\x85\x18\x00\x00\x00\x48\x8b\x45\x18\x50\x48\xc7\xc0\x01"\

"\x00\x00\x00\x50\x48\x8b\x3c\x24\x48\x8b\x74\x24\x08\x48\x8b\x54\x24\x10\x48\xc7\xc0\x04\x00\x00"\

"\x00\x0f\x05\x48\x83\xc4\x18\x48\xc7\xc0\x00\x00\x00\x00\x50\x48\x8b\x3c\x24\x48\xc7"\

"\xc0\x3c\x00\x00\x00\x0f\x05\x48\x83\xc4\x08\x48\x81\xc4\x80\x00\x00\x00"\

"\x5d\xc3";


In case you just want to execute the input, you may use the `-x` option.

-x execute (just-in-time)


$ cat code1.c

int main()

{

write(1, "Hello World\n", 13);

exit(0);

}

$ ragg2 -x code1.c

Hello World


## Shellcode and Encoders

ragg2 offers a few ready-made shellcodes and encoders.

$ ragg2 -L

shellcodes:

exec : execute cmd=/bin/sh suid=false

encoders:

xor : xor encoder for shellcode


Using the '-i' option, one can generate specify and generate the shellcode.

$ ragg2 -i exec

31c048bbd19d9691d08c97ff48f7db53545f995257545eb03b0f05


Similar to the previous section, the output format(c, raw, elf etc.,) can be specified here too along with the architecture and bits.

ragg2 offers an xor encoder too. The following are the relevant flags/options.

$ ragg2 -h

-c [k=v] set configuration options

-E [encoder] use specific encoder. see -L

-L list all plugins (shellcodes and encoders)


$ ragg2 -E xor -c key=32 -i exec

6a1b596a205be8ffffffffc15e4883c60d301e48ffc6e2f911e0689bf1bdb6b1f0acb7df68d7fb73747fb97277747e901b2f25


The same can be done with a .c or .r file output. The first one is the normal output(machine code) and the second is xor encoded.

$ ragg2 -a x86 -f raw code1.c

eb0e66666666662e0f1f84000000000050bf01000000488d359f000000ba0d000000e81900000031ff89442404e85e00000031d289042489d059c30f1f440000897c24fc48897424f0895424ec8b5424fc895424dc488b7424f048897424d08b5424ec895424cc8b7c24dc488b7424d08b5424ccb8010000000f0548894424e0488b4424e089c1894c24c88b4424c8c3897c24fc8b7c24fc897c24ec8b7c24ecb83c0000000f0548894424f0488b4424f089c1894c24e88b4424e8c348656c6c6f20576f726c640a00

$ ragg2 -E xor -c key=127 -a x86 -f raw code1.c

6ac9596a7f5be8ffffffffc15e4883c60d301e48ffc6e2f994711919191919517060fb7f7f7f7f7f2fc07e7f7f7f37f24ae07f7f7fc5727f7f7f97667f7f7f4e80f63b5b7b97217f7f7f4eadf67b5bf6af26bc70603b7f7ff6035b8337f60b5b8ff62b5b93f42b5b83f62b5ba337f40b5b8f37f60b5baff42b5b93f62b5bb3f4035ba337f40b5baff42b5bb3c77e7f7f7f707a37f63b5b9f37f43b5b9ff6bef6335bb7f43b5bb7bcf6035b83f4035b83f6035b93f4035b93c7437f7f7f707a37f63b5b8f37f43b5b8ff6bef6335b97f43b5b97bc371a1313105f28100d131b757f


## Appending and patching data

If you want to append/patch some bytes to your output, here are a few options ragg2 offers.

-B [hexpairs] append some hexpair bytes

-C [file] append contents of file

-d [off:dword] patch dword (4 bytes) at given offset

-D [off:qword] patch qword (8 bytes) at given offset

-n [dword] append 32bit number (4 bytes)

-N [dword] append 64bit number (8 bytes)

-p [padding] add padding after compilation (padding=n10s32)

ntas : begin nop, trap, 'a', sequence

NTAS : same as above, but at the end

-S [string] append a string

-w [off:hex] patch hexpairs at given offset