ixty / mandibule Goto Github PK
View Code? Open in Web Editor NEWlinux elf injector for x86 x86_64 arm arm64
linux elf injector for x86 x86_64 arm arm64
For my last issue: #2
I commit the patch: Hackerl@92de629
unsigned long mandibule_beg(int aligned)
{
if(!aligned)
return (unsigned long)mandibule_beg;
unsigned long align_size = (unsigned long)mandibule_beg % 0x1000;
return (unsigned long)mandibule_beg - (align_size == 0 ? 0x1000 : align_size);
}
After successful compilation, it can run successfully, but the process is stuck.
I modified the source code to output detailed logs, and found that the program was stuck in a system call.
stuck log:
./mandibule $(pwd)/toinject $(pidof target)
> syscall: 10
> syscall: 9
> syscall: 9
> syscall: 9
> syscall: 9
> syscall: 9
> syscall: 9
> syscall: 9
> syscall: 9
> syscall: 3
> syscall: 3
> syscall: 158
> syscall: 158
> syscall: 18446744073709551615
> syscall: 18446744073709551615
> syscall: 18446744073709551615
> syscall: 18446744073709551615
> syscall: 18446744073709551615
> syscall: 18446744073709551615
> syscall: 18446744073709551615
> syscall: 18446744073709551615
after syscall 158, the output of syscall will be messy, so I guess there is a problem with the system call 158.
What's interesting is that I shortened the name of the injected program "toinject" a bit, and renamed it to "toinj" and it could run successfully.
success log:
./mandibule $(pwd)/toinj $(pidof target)
> syscall: 10
> syscall: 9
> syscall: 9
> syscall: 9
> syscall: 9
> syscall: 9
> syscall: 9
> syscall: 9
> syscall: 9
> syscall: 3
> syscall: 3
> syscall: 158
> syscall: 158
> syscall: 10
> syscall: 10
> syscall: 10
> syscall: 10
> syscall: 10
> syscall: 10
> syscall: 11
> syscall: 11
> syscall: 39
> syscall: 39
> syscall: 5
> syscall: 5
> syscall: 12
> syscall: 12
> syscall: 12
> syscall: 12
> syscall: 1
> syscall: 1
> syscall: 1
> syscall: 1
> syscall: 1
> syscall: 1
> syscall: 35
> syscall: 35
> syscall: 1
> syscall: 1
> syscall: 35
> syscall: 35
> syscall: 1
> syscall: 1
> syscall: 35
> syscall: 35
> syscall: 1
> syscall: 1
> syscall: 231
> shellcode executed!
> restored memory & registers
> successfully injected shellcode into pid 15313
Can continue to run after the system call 158, I am going to debug further, I will add information here later.
I want to know the purpose of this environment variable.
FSTACK_PUSH_STR(sp, "MANMAP=1");
for(int i=0; i<ehdr->e_phnum; i++)
{
phdr = (elf_phdr *)(elf_buf + ehdr->e_phoff + i * ehdr->e_phentsize);
// printf("> seg[%d] load: %d addr 0x%llx size 0x%llx\n", i, phdr->p_type == PT_LOAD, phdr->p_vaddr, phdr->p_memsz);
if(phdr->p_type == PT_LOAD && load_segment(elf_buf, ehdr, phdr, base_off))
return -1;
if(!base_seg)
base_seg = phdr->p_vaddr;
base_next = phdr->p_vaddr + phdr->p_memsz > base_next ? phdr->p_vaddr + phdr->p_memsz : base_next;
}
ALIGN_PAGE_DOWN(base_seg);
if(ehdr->e_type == ET_DYN)
base_seg += base_off;
// printf("> program base: 0x%llx\n", base_seg);
Now the code to get the base address is written like this, get the non-zero offset of any segment (phdr->p_vaddr). But when I compile the program with the "-static-pie" option, the section information is as follows.
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x00000000000e6965 0x00000000000e6965 R E 0x200000
LOAD 0x00000000000e7188 0x00000000002e7188 0x00000000002e7188
0x0000000000007360 0x000000000000b550 RW 0x200000
DYNAMIC 0x00000000000ed8e8 0x00000000002ed8e8 0x00000000002ed8e8
0x0000000000000170 0x0000000000000170 RW 0x8
TLS 0x00000000000e7188 0x00000000002e7188 0x00000000002e7188
0x0000000000000000 0x0000000000000010 R 0x8
GNU_EH_FRAME 0x00000000000bb650 0x00000000000bb650 0x00000000000bb650
0x000000000000697c 0x000000000000697c R 0x4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x10
GNU_RELRO 0x00000000000e7188 0x00000000002e7188 0x00000000002e7188
0x0000000000006e78 0x0000000000006e78 R 0x1
You can see that the first segment is LOAD, but its virtual address is 0, then the program is judging that "if (!base_seg)" will enter the branch, so the final value of "base_seg" is "2e7188", the second Load segment Virtual address.
"base_seg" should take the virtual address of the first LOAD segment, whether it is zero or not.
int base_set = 0;
for(int i=0; i<ehdr->e_phnum; i++)
{
phdr = (elf_phdr *)(elf_buf + ehdr->e_phoff + i * ehdr->e_phentsize);
// printf("> seg[%d] load: %d addr 0x%llx size 0x%llx\n", i, phdr->p_type == PT_LOAD, phdr->p_vaddr, phdr->p_memsz);
if(phdr->p_type == PT_LOAD)
{
if(!base_set)
{
base_set = 1;
base_seg = phdr->p_vaddr;
}
if (load_segment(elf_buf, ehdr, phdr, base_off))
return -1;
}
base_next = phdr->p_vaddr + phdr->p_memsz > base_next ? phdr->p_vaddr + phdr->p_memsz : base_next;
}
FSTACK_PUSH_LONG(sp, 0);
for(int i=0; i<ac; i++)
FSTACK_PUSH_LONG(sp, (unsigned long)av_0 + (ac - i - 1) * sizeof(unsigned long));
// argc
FSTACK_PUSH_LONG(sp, ac);
"(unsigned long)av_0 + (ac - i - 1) * sizeof(unsigned long)" not the correct string pointer, each parameter has a different length.
The correct pointer should be temporarily saved after the parameter is pushed onto the stack.
commit: Hackerl@0ba0a46
Good work on the method for injection with fPIE
compilation ELF!
I am not so sure why I have problem with the build, as per seen in the the title or in the error snip below.
It seems that the macro
(for arch recognition) is having a problem or icrt_syscall.h
has been conflicted with /usr/include/unistd.h
?
If you would be kind to upload the mandiblue you compiled for the both architecture in the repo or onto virus total etc, it would be very helpful. I am onto reproduction the method your described.
I use Debian for the purpose, and doing plenty of build on the other apps without problem.. Thank you.
On x32:
$ make x86
rm -rf mandibule target toinject
cc -D_GNU_SOURCE -std=gnu99 -static-libgcc -lgcc -I icrt/ -I code/ -fno-common -fno-stack-protector -fomit-frame-pointer -fno-exceptions -fno-asynchronous-unwind-tables -fno-unwind-tables -pie -fPIE -fno-builtin -nostdlib -m32 -o mandibule mandibule.c
In file included from /usr/include/i386-linux-gnu/sys/user.h:25:0,
from code/ptinject.h:15,
from mandibule.c:28:
/usr/include/unistd.h:603:13: error: conflicting types for '_exit'
extern void _exit (int __status) __attribute__ ((__noreturn__));
^
In file included from icrt/icrt.h:15:0,
from mandibule.c:25:
icrt/icrt_syscall.h:169:25: note: previous definition of '_exit' was here
_syscall1(SYS_exit, _exit, int, int);
^
icrt/icrt_syscall.h:149:23: note: in definition of macro '_syscall1'
static inline rettype sys_name(t1 a1) \
^
Makefile:25: recipe for target 'x86' failed
make: *** [x86] Error 1
On x64:
$ make x86_64
rm -rf mandibule target toinject
cc -D_GNU_SOURCE -std=gnu99 -static-libgcc -lgcc -I icrt/ -I code/ -fno-common -fno-stack-protector -fomit-frame-pointer -fno-exceptions -fno-asynchronous-unwind-tables -fno-unwind-tables -pie -fPIE -fno-builtin -nostdlib -o mandibule mandibule.c
In file included from /usr/include/x86_64-linux-gnu/sys/user.h:25:0,
from code/ptinject.h:15,
from mandibule.c:28:
/usr/include/unistd.h:603:13: error: conflicting types for '_exit'
extern void _exit (int __status) __attribute__ ((__noreturn__));
^
In file included from icrt/icrt.h:15:0,
from mandibule.c:25:
icrt/icrt_syscall.h:169:25: note: previous definition of '_exit' was here
_syscall1(SYS_exit, _exit, int, int);
^
icrt/icrt_syscall.h:149:23: note: in definition of macro '_syscall1'
static inline rettype sys_name(t1 a1) \
^
Makefile:32: recipe for target 'x86_64' failed
make: *** [x86_64] Error 1
end of issue
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.