{"id":13685810,"url":"https://github.com/0xswitch/Hellf","last_synced_at":"2025-05-01T04:32:23.893Z","repository":{"id":51189379,"uuid":"245675449","full_name":"0xswitch/Hellf","owner":"0xswitch","description":"ELF patching library in Python","archived":false,"fork":false,"pushed_at":"2021-03-15T14:17:33.000Z","size":494,"stargazers_count":24,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-21T14:36:46.802Z","etag":null,"topics":["elf","patching","reverse"],"latest_commit_sha":null,"homepage":"https://0xswitch.fr","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/0xswitch.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-03-07T17:24:24.000Z","updated_at":"2024-05-19T22:45:01.000Z","dependencies_parsed_at":"2022-09-26T17:50:29.840Z","dependency_job_id":null,"html_url":"https://github.com/0xswitch/Hellf","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xswitch%2FHellf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xswitch%2FHellf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xswitch%2FHellf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xswitch%2FHellf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/0xswitch","download_url":"https://codeload.github.com/0xswitch/Hellf/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251824615,"owners_count":21649901,"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","patching","reverse"],"created_at":"2024-08-02T14:00:57.555Z","updated_at":"2025-05-01T04:32:23.579Z","avatar_url":"https://github.com/0xswitch.png","language":"Python","funding_links":[],"categories":["Awesome Repositories"],"sub_categories":["ELF binary format"],"readme":"# Hellf ![](./img/logo.png)\n\n\n\nthis is just a bad joke between hell and elf :(\n\nThe aim of this project is to provide a python library for patching ELF binary file. It only supports for the moment `x86` and `x86_64` architecture.\n\n\n\n[![made-with-python](https://img.shields.io/badge/Made%20with-Python-1f425f.svg)](https://www.python.org/) [![Ask Me Anything !](https://img.shields.io/badge/Ask%20me-anything-1abc9c.svg)](https://GitHub.com/Naereen/ama) ![Twitter Follow](https://img.shields.io/twitter/follow/swuitch?label=ping%20%40swuitch\u0026style=social) [![pypi](https://img.shields.io/pypi/v/Hellf)](https://pypi.org/project/Hellf/)\n\n```\npip install Hellf\n```\n\n\n```python\nfrom Hellf import ELF\nfrom pwn import shellcraft, asm, context\ncontext.arch = \"amd64\"\n\ne = ELF(\"/bin/ls\")\n\ne.get_section_by_name(\".text\").data = asm(shellcraft.amd64.sh())\ne.Elf64_Ehdr.e_entry = e.get_section_by_name(\".text\").sh_addr\n\ne.save(\"/tmp/not_really_ls_anymore\")\n```\n\n![img/poc.gif](img/twitter.gif)\n\n# Use cases\n\nHellf allows you to modify each par of the ELF.\n\n- Program Header (segments definitions)\n- Section Header (sections definitions)\n- Section data (.text, .plt, .data, .bss, ...)\n\nYou can change every single byte of a given binary.\n\n## Adding a section\n\n```python\nnew_section = Elf64_Shdr_ST()\n\n# creating our shellcode (exit(14);)\nasm = \"\"\"\n    mov rax, 0x3c\n    mov rdi, 14\n    syscall\n    \"\"\"\n\nks = Ks(KS_ARCH_X86, KS_MODE_64)\nks.syntax = KS_OPT_SYNTAX_NASM\n\nshellcode = ks.asm(asm)[0]\nshellcode = (c_char * len(shellcode)).from_buffer(bytearray(shellcode)).raw\n\nnew_section.data = shellcode\n\nnew_section.sh_name       = 1                      # choose a random name\nnew_section.sh_offset     = e.Elf64_Ehdr.e_shoff\nnew_section.sh_size       = len(new_section.data)\nnew_section.sh_addralign  = 16\nnew_section.sh_type       = 0x1                    # PROGBITS\n\n# adding our sections in the Section Header table\ne.add_section(new_section)\n```\n\n## Extending segment\n\n```Python\n# need to extend the last segment to englobe our new section\nsegment = e.Elf64_Phdr[5]\n\nsegment.p_filesz \t= new_section.sh_offset + new_section.sh_size - segment.p_offset\nsegment.p_memsz \t= new_section.sh_offset + new_section.sh_size - segment.p_offset\nsegment.p_flags \t= 7 # RWX\n\n# modifying our entrypoint to point to the shellcode\ne.Elf64_Ehdr.e_entry = segment.p_vaddr - segment.p_offset + new_section.sh_offset\n\ne.save(\"/tmp/exit\")\n```\n\n# Embuche\n\nHellf is a part of [Embuche](https://github.com/magnussen7/Embuche), a lot of Hellf scripts are used to obfuscate ELF for the purpose of this project. The scripts used are described here : [File Format Hacks](https://github.com/magnussen7/Embuche/blob/master/README.md#file-format-hacks)\n\nFor example it used to create a fake `.dynsym` section or to hide the entry point [link to script](https://github.com/magnussen7/Embuche/blob/master/class_embuche/cmake_bakery/hellf_scripts/mixing_symbols_table.py)\n\nBut Hellf is also the corner stone of the Embuche metamorphic packer.\n\n\u003e A metamorphic packer is available in Embuche. This packer will load your binary and cipher it (AES 256 bits CBC).\n\u003e\n\u003e If you decide to use the packer, your program will be ciphered and stored in a section of our packer. When you will execute your program the packer will copy itself in memory, unciphered your program and write it on the disk for execution.\n\u003e\n\u003e Beside cipher your binary, the packer will also ensure its integrity. The encryption keys used for the encryption are based on the SHA sum of the `.text` section, so if the packer or your program is being debugged the SHA sum will be different of the one used for decryption.\n\u003e\n\u003e The ELF of the packer can be modified with the `packer_embuche` options.\n\n# Documentation\n\nThere is almost no documentation for the moment although the code is a bit commented, you should be lucky.\n\nHere a list of function of the `ELF` object.\n\n```python\nget_section_number(name)\nget_section_by_name(name)\nget_section_name(shstrtab_index)\nadd_section(custom_section)\n```\n\nFor the remaining, you should just interact with the object attributes them self. About the names of variables I just used the official one provided by the ABI.\n\n- /usr/include/elf.h\n- [http://www.sco.com/developers/gabi/latest/contents.html](http://www.sco.com/developers/gabi/latest/contents.html)\n\n\nFor example, the ELF Header :\n```\ntypedef struct\n{\n  unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */\n  Elf64_Half    e_type;                 /* Object file type */\n  Elf64_Half    e_machine;              /* Architecture */\n  Elf64_Word    e_version;              /* Object file version */\n  Elf64_Addr    e_entry;                /* Entry point virtual address */\n  Elf64_Off     e_phoff;                /* Program header table file offset */\n  Elf64_Off     e_shoff;                /* Section header table file offset */\n  Elf64_Word    e_flags;                /* Processor-specific flags */\n  Elf64_Half    e_ehsize;               /* ELF header size in bytes */\n  Elf64_Half    e_phentsize;            /* Program header table entry size */\n  Elf64_Half    e_phnum;                /* Program header table entry count */\n  Elf64_Half    e_shentsize;            /* Section header table entry size */\n  Elf64_Half    e_shnum;                /* Section header table entry count */\n  Elf64_Half    e_shstrndx;             /* Section header string table index */\n} Elf64_Ehdr;\n```\n\nSo you can just do this to interact with the section or section header :\n\n```python\n\u003e  e.Elf64_Shdr[26]\nELF Sections header struct\n  sh_name:      0x1\n  sh_type:      0x3\n  sh_flags:     0x0\n  sh_addr:      0x0\n  sh_offset:    0x222b4\n  sh_size:      0xf7\n  sh_link:      0x0\n  sh_info:      0x0\n  sh_addralign: 0x1\n  sh_entsize:   0x0\n\n\u003e e.Elf64_Shdr[26].data\nb'\\x00.shstrtab\\x00.interp\\x00.note.gnu.build-id\\x00.note.ABI-tag\\x00.gnu.hash\\x00.dynsym\\x00.dynstr\\x00.gnu.version\\x00.gnu.version_r\\x00.rela.dyn\\x00.rela.plt\\x00.init\\x00.text\\x00.fini\\x00.rodata\\x00.eh_frame_hdr\\x00.eh_frame\\x00.init_array\\x00.fini_array\\x00.data.rel.ro\\x00.dynamic\\x00.got\\x00.data\\x00.bss\\x00.comment\\x00'\n\n\u003e e.get_section_name(e.Elf64_Shdr[26].sh_name)\n'.shstrtab'\n```\n\nOr if you want to interact with the header itself.\n\n````python\n\u003e e.Elf64_Ehdr\nELF Header struct\n  e_ident:      0x7f 0x45 0x4c 0x46 0x2 0x1 0x1 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0\n  e_type:       0x3\n  e_machine:    0x3e\n  e_version:    0x1\n  e_entry:      0x5b20\n  e_phoff:      0x40\n  e_shoff:      0x2234b\n  e_flags:      0x0\n  e_ehsize:     0x40\n  e_phentsize:  0x38\n  e_phnum:      0xb\n  e_shentsize:  0x40\n  e_shnum:      0x1b\n  e_shstrndx:   0x1a\n\n\u003e hex(e.Elf64_Ehdr.e_entry)\n'0x5b20'\n\n\u003e hex(e.Elf64_Ehdr.e_shnum)\n'0x1b'\n\n\u003e hex(e.Elf64_Ehdr.e_shoff)\n'0x2234b'\n````\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0xswitch%2FHellf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F0xswitch%2FHellf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0xswitch%2FHellf/lists"}