How to Modify or Patch the Compiled Executable (inplace, reverse engineering)?


I have a compiled .o file, and how to modify a string constant in it? for example, change “hello” to “HELLO”.

Let’s take a look at this simple C source code that outputs “Hello World!”.

1
2
3
4
5
6
7
// test.c
#include <stdio.h>
 
int main() {
        printf("Hello World!\n");
        return 0;
}
// test.c
#include <stdio.h>

int main() {
        printf("Hello World!\n");
        return 0;
}

Let’s compile this:

1
gcc -o test.o test.c
gcc -o test.o test.c

And execute it should output:

1
2
$ ./test.o
Hello World!
$ ./test.o
Hello World!

If we “cat” the file, it of course will show some random characters which is normal, because many characters/values are non-printable.




@@@@��((uu   ���-�=�=X`�-�=�=��8880hhhDDS�td8880P�td   44Q�tdR�td�-�=�=HH/lib64/ld-linux-x86-64.so.2 GNU���GNUR׫+{�����M0�~�GNU��e�mH "d s "__cxa_finalize__libc_start_mainputslibc.so.6GLIBC_2.2.5GLIBC_2.34_ITM_deregisterTMCloneTable__gmon_start___ITM_registerTMCloneTable'ui       1���=�@@�?�?�?�?�?�?��H�H��/H��t��H���5�/��%�/��h�����������%�/D����%u/D��1�I��^H��H���PTE1�1�H�=��S/�f.�H�=y/H�r/H9�tH�6/H��t    �����H�=I/H�5B/H)�H��H��?H��H�H��tH�/H����fD�����=/u+UH�=�.H��t
                                                                                                                                                                                                          H�=�.�����d�����.]������w�����UH��H��H��������]���H�H��Hello World!0                               ����&D$4���� FJ
U                                                                         ���d,����<����L���L5����zRx                    �?:*3$"\����t�����q���E�C
 @'
h��=���o���
�
 �?P�  ���o���o ���o���o���o�=0@GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0��    � ��� �3I@U�=|@��=������� ����=� ��?�
                                                                                                                                                                             G @'8@?hE@R a@n }@K`&�@�I�@� �"�
                                                Scrt1.o__abi_tagcrtstuff.cderegister_tm_clones__do_global_dtors_auxcompleted.0__do_global_dtors_aux_fini_array_entryframe_dummy__frame_dummy_init_array_entrytest.c__FRAME_END___DYNAMIC__GNU_EH_FRAME_HDR_GLOBAL_OFFSET_TABLE___libc_start_main@GLIBC_2.34_ITM_deregisterTMCloneTableputs@GLIBC_2.2.5_edata_fini__data_start__gmon_start____dso_handle_IO_stdin_used_end__bss_startmain__TMC_END___ITM_registerTMCloneTable__cxa_finalize@GLIBC_2.2.5_init.symtab.strtab.shstrtab.interp.note.gnu.property.note.gnu.build-id.note.ABI-tag.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.got.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.init_array.fini_array.dynamic.data.bss.comment#886hh$I�� W���o��$a
                                                                                                                                                                ���i���q���o~���o  0�PP��                                                                                                                                                                                                               �  �  4�H H ������=�-���?�@0�hh
                                                   @00+@0`       �3�z5

Modify the Binary Executable using Sed

We can simply using the sed to replace some texts so that the binary prints a different string:

1
2
3
4
$ cat test.o | sed "s/World/AAAAA/g" > a.o
$ chmod +x ./a.o
$ ./a.o
Hello AAAAA!
$ cat test.o | sed "s/World/AAAAA/g" > a.o
$ chmod +x ./a.o
$ ./a.o
Hello AAAAA!

However, if you replace the string with a different length, it will not work because of the ELF format, most of the time, the modified binary will crash with "Segmentation fault" error.

Modify the Binary Executable using xxd

xxd is a linux utility that allows to print the binary using Hexidecimal printable characters, for example, the following prints the first 10 lines of the xxd dump of the binary:

1
2
3
4
5
6
7
8
9
10
11
$ xxd test.o | head
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............
00000010: 0300 3e00 0100 0000 6010 0000 0000 0000  ..>.....`.......
00000020: 4000 0000 0000 0000 9836 0000 0000 0000  @........6......
00000030: 0000 0000 4000 3800 0d00 4000 1f00 1e00  ....@.8...@.....
00000040: 0600 0000 0400 0000 4000 0000 0000 0000  ........@.......
00000050: 4000 0000 0000 0000 4000 0000 0000 0000  @.......@.......
00000060: d802 0000 0000 0000 d802 0000 0000 0000  ................
00000070: 0800 0000 0000 0000 0300 0000 0400 0000  ................
00000080: 1803 0000 0000 0000 1803 0000 0000 0000  ................
00000090: 1803 0000 0000 0000 1c00 0000 0000 0000  ................
$ xxd test.o | head
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............
00000010: 0300 3e00 0100 0000 6010 0000 0000 0000  ..>.....`.......
00000020: 4000 0000 0000 0000 9836 0000 0000 0000  @........6......
00000030: 0000 0000 4000 3800 0d00 4000 1f00 1e00  [email protected]...@.....
00000040: 0600 0000 0400 0000 4000 0000 0000 0000  ........@.......
00000050: 4000 0000 0000 0000 4000 0000 0000 0000  @.......@.......
00000060: d802 0000 0000 0000 d802 0000 0000 0000  ................
00000070: 0800 0000 0000 0000 0300 0000 0400 0000  ................
00000080: 1803 0000 0000 0000 1803 0000 0000 0000  ................
00000090: 1803 0000 0000 0000 1c00 0000 0000 0000  ................

Then, we can save this output to a text file, modify the values of the text in HEX, and then use the following command to re-construct the binary.

1
2
$ xxd test.o | grep World
00002000: 0100 0200 4865 6c6c 6f20 576f 726c 6421  ....Hello World!
$ xxd test.o | grep World
00002000: 0100 0200 4865 6c6c 6f20 576f 726c 6421  ....Hello World!

Then, we can do this to patch or inject data to the binary:

1
2
3
4
5
$ xxd test.o | sed "s/576f 726c 6421/4141 4141 4141/g" > test.txt
$ xxd -r test.txt > b.o
$ chmod +x b.o
$ ./b.o
Hello AAAAAA
$ xxd test.o | sed "s/576f 726c 6421/4141 4141 4141/g" > test.txt
$ xxd -r test.txt > b.o
$ chmod +x b.o
$ ./b.o
Hello AAAAAA

So, the modified binary manages to run and prints a different message (injected).

We can confirm that the modified binary has changed by dumping the byte code (assembly): How to View the Byte Code (Dis-assembler) of a Compiled Executable?

--EOF (The Ultimate Computing & Technology Blog) --

GD Star Rating
loading...
756 words
Last Post: How to View the Byte Code (Dis-assembler) of a Compiled Executable?
Next Post: How to Get the Gas Price and Gas Fee on Ethereum Blockchain?

The Permanent URL is: How to Modify or Patch the Compiled Executable (inplace, reverse engineering)?

Leave a Reply