Intel CET (Control-flow Enforcement Technology)
{endbr64, endbr32} at target of computed jmp/call; 'notrack' at source
modified: stub/src/amd64-linux.elf-entry.S
modified: stub/src/amd64-linux.elf-fold.S
modified: stub/src/amd64-linux.elf-main2.c
modified: stub/src/arch/amd64/macros.S
modified: stub/src/arch/i386/macros.S
modified: stub/src/i386-expand.S
modified: stub/src/i386-linux.elf-entry.S
modified: stub/src/i386-linux.elf-fold.S
modified: stub/src/i386-linux.elf-main2.c
This commit is contained in:
parent
7e75491e88
commit
3869a67180
@ -86,6 +86,7 @@ M_NRV2E_LE32=8
|
|||||||
section ELFMAINX
|
section ELFMAINX
|
||||||
sz_pack2= .-4
|
sz_pack2= .-4
|
||||||
_start: .globl _start
|
_start: .globl _start
|
||||||
|
endbr64
|
||||||
//// nop; int3 # uncomment for debugging
|
//// nop; int3 # uncomment for debugging
|
||||||
|
|
||||||
pop %rcx // argc
|
pop %rcx // argc
|
||||||
@ -304,6 +305,7 @@ here: // OUT: %rdi= (2+ retaddrj) without disturbing shadow stack
|
|||||||
ret
|
ret
|
||||||
|
|
||||||
getbit:
|
getbit:
|
||||||
|
.byte 0xf3,0x0f,0x1e,0xfa // endbr64 // from "call *%rdx"
|
||||||
addl bits,bits; jz refill // Carry= next bit
|
addl bits,bits; jz refill // Carry= next bit
|
||||||
rep; ret
|
rep; ret
|
||||||
refill:
|
refill:
|
||||||
|
|||||||
@ -86,6 +86,7 @@ PAGE_MASK: .quad -1<<12 // default
|
|||||||
// no 'section', thus '.text'; also loaded first in amd64-linux.elf-fold.bin.
|
// no 'section', thus '.text'; also loaded first in amd64-linux.elf-fold.bin.
|
||||||
// Code from amd64-linux.elf-main.c is also .text, and is next.
|
// Code from amd64-linux.elf-main.c is also .text, and is next.
|
||||||
fold_begin:
|
fold_begin:
|
||||||
|
endbr64
|
||||||
//// int3 # DEBUG
|
//// int3 # DEBUG
|
||||||
mov %r13,F_UNMAPA(%rbp)
|
mov %r13,F_UNMAPA(%rbp)
|
||||||
mov %r13,%rax; and $is_ptinterp,%eax; or %eax,F_ELFA(%rbp)
|
mov %r13,%rax; and $is_ptinterp,%eax; or %eax,F_ELFA(%rbp)
|
||||||
@ -202,7 +203,7 @@ no_pse_map:
|
|||||||
pop %arg1 # ADRU: unfolded upx_main etc.
|
pop %arg1 # ADRU: unfolded upx_main etc.
|
||||||
pop %arg2 # LENU
|
pop %arg2 # LENU
|
||||||
push $__NR_munmap; pop %rax
|
push $__NR_munmap; pop %rax
|
||||||
jmp *(%r14) # goto: syscall; pop %rdx; ret
|
/*notrack*/ jmp *(%r14) # goto: syscall; pop %rdx; ret
|
||||||
|
|
||||||
get_page_mask: .globl get_page_mask
|
get_page_mask: .globl get_page_mask
|
||||||
mov PAGE_MASK(%rip),%rax
|
mov PAGE_MASK(%rip),%rax
|
||||||
|
|||||||
@ -253,16 +253,22 @@ make_hatch_x86_64(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
char *hatch = next_unc;
|
char *hatch = next_unc;
|
||||||
unsigned const sz_code = 4;
|
int code[3] = {
|
||||||
|
0xfa1e0ff3, // endbr64
|
||||||
|
0x585a050f, // syscall; pop %arg3{%rdx}; pop %rax
|
||||||
|
0x90e0ff3e, // notrack jmp *%rax; nop
|
||||||
|
};
|
||||||
DPRINTF("make_hatch %%p %%p %%x\\n", phdr, next_unc, frag_mask);
|
DPRINTF("make_hatch %%p %%p %%x\\n", phdr, next_unc, frag_mask);
|
||||||
if (phdr->p_type==PT_LOAD && phdr->p_flags & PF_X) {
|
if (phdr->p_type==PT_LOAD && phdr->p_flags & PF_X) {
|
||||||
if (sz_code <= (frag_mask & -(long)hatch)) {
|
if (sizeof(code) <= (unsigned)(frag_mask & -(long)hatch)) {
|
||||||
((long *)hatch)[0] = 0xc35a050f; // syscall; pop %arg3{%rdx); ret
|
((int *)hatch)[0] = code[0]; // endbr64
|
||||||
|
((int *)hatch)[1] = code[1]; // syscall; pop %arg3{%rdx}; pop %rax
|
||||||
|
((int *)hatch)[2] = code[2]; // notrack jmp *%rax; nop
|
||||||
}
|
}
|
||||||
else { // Does not fit at hi end of .text, so must use a new page "permanently"
|
else { // Does not fit at hi end of .text, so must use a new page "permanently"
|
||||||
int mfd = upxfd_create(addr_string("upx"), MFD_EXEC); // the directory entry
|
int mfd = upxfd_create(addr_string("upx"), MFD_EXEC); // the directory entry
|
||||||
write(mfd, addr_string("\x0f\x05\x5a\xc3"), sz_code);
|
write(mfd, &code, sizeof(code));
|
||||||
hatch = mmap(0, sz_code, PROT_READ|PROT_EXEC, MAP_SHARED, mfd, 0);
|
hatch = mmap(0, sizeof(code), PROT_READ|PROT_EXEC, MAP_SHARED, mfd, 0);
|
||||||
close(mfd);
|
close(mfd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,4 +41,8 @@
|
|||||||
.code64
|
.code64
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
.macro endbr64
|
||||||
|
.byte 0xf3,0x0f,0x1e,0xfa
|
||||||
|
.endm
|
||||||
|
|
||||||
// vi:ts=8:et:nowrap
|
// vi:ts=8:et:nowrap
|
||||||
|
|||||||
@ -717,4 +717,8 @@ section LXUNF035
|
|||||||
ret
|
ret
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
.macro endbr32
|
||||||
|
.byte 0xf3,0x0f,0x1e,0xfb
|
||||||
|
.endm
|
||||||
|
|
||||||
// vi:ts=8:et:nowrap
|
// vi:ts=8:et:nowrap
|
||||||
|
|||||||
@ -77,6 +77,9 @@ sz_binfo= 3*4
|
|||||||
|
|
||||||
f_unfilter: // (*f_unf)(xo->buf, out_len, h.b_cto8, h.b_ftid);
|
f_unfilter: // (*f_unf)(xo->buf, out_len, h.b_cto8, h.b_ftid);
|
||||||
#include "arch/i386/bxx.S"
|
#include "arch/i386/bxx.S"
|
||||||
|
.macro endbr32
|
||||||
|
.byte 0xf3,0x0f,0x1e,0xfb
|
||||||
|
.endm
|
||||||
|
|
||||||
// int f_expand(nrv_byte const *src, nrv_byte *dst, size_t *dstlen) // C-callable
|
// int f_expand(nrv_byte const *src, nrv_byte *dst, size_t *dstlen) // C-callable
|
||||||
// Includes unfilter and cache flush.
|
// Includes unfilter and cache flush.
|
||||||
@ -128,6 +131,7 @@ refill:
|
|||||||
movzbl (%esi),%edx // pre-fetch: literal, or bottom 8 bits of offset
|
movzbl (%esi),%edx // pre-fetch: literal, or bottom 8 bits of offset
|
||||||
rep; ret
|
rep; ret
|
||||||
getbit:
|
getbit:
|
||||||
|
endbr32 // from "call *%edx"
|
||||||
addl bits,bits; jz refill // Carry= next bit
|
addl bits,bits; jz refill // Carry= next bit
|
||||||
rep; ret
|
rep; ret
|
||||||
|
|
||||||
|
|||||||
@ -104,6 +104,7 @@ M_NRV2B_LE32= 2
|
|||||||
section ELFMAINX
|
section ELFMAINX
|
||||||
sz_pack2 = -NBPW+ _start
|
sz_pack2 = -NBPW+ _start
|
||||||
_start: .globl _start
|
_start: .globl _start
|
||||||
|
endbr32
|
||||||
/// nop; int3 // DEBUG i386 entry.S
|
/// nop; int3 // DEBUG i386 entry.S
|
||||||
call L70 // MATCH_08 push $&getbit
|
call L70 // MATCH_08 push $&getbit
|
||||||
L70ret:
|
L70ret:
|
||||||
@ -322,7 +323,7 @@ eof_n2b:
|
|||||||
|
|
||||||
mov F_ADRU(%ebp),%eax
|
mov F_ADRU(%ebp),%eax
|
||||||
add $D_FOLD,%eax // PAGE_MASK, upxfd_path, mflg_data
|
add $D_FOLD,%eax // PAGE_MASK, upxfd_path, mflg_data
|
||||||
jmp *%eax
|
/*notrack*/ jmp *%eax
|
||||||
// %esp:
|
// %esp:
|
||||||
// MATCH_13 ptr unfolded_code; for escape hatch
|
// MATCH_13 ptr unfolded_code; for escape hatch
|
||||||
// MATCH_12 len unfolded code; for escape hatch
|
// MATCH_12 len unfolded code; for escape hatch
|
||||||
|
|||||||
@ -101,7 +101,9 @@ upxfn_path= . - 2*NBPW // displacement to filename string
|
|||||||
mflg_data= . - 1*NBPW // QNZ vs Linux
|
mflg_data= . - 1*NBPW // QNZ vs Linux
|
||||||
|
|
||||||
fold_begin:
|
fold_begin:
|
||||||
|
endbr32
|
||||||
//// int3 // DEBUG
|
//// int3 // DEBUG
|
||||||
|
endbr32
|
||||||
pop ebx; push ebx // F_ADRX: elfaddr + (O_BINFO | is_ptinterp | unmap_all_pages)
|
pop ebx; push ebx // F_ADRX: elfaddr + (O_BINFO | is_ptinterp | unmap_all_pages)
|
||||||
jmp L10
|
jmp L10
|
||||||
|
|
||||||
@ -285,7 +287,7 @@ L60:
|
|||||||
push eax // 32 bytes of zeroes now on stack, ready for 'popa'
|
push eax // 32 bytes of zeroes now on stack, ready for 'popa'
|
||||||
|
|
||||||
mov al, __NR_munmap // eax was 0 from L60
|
mov al, __NR_munmap // eax was 0 from L60
|
||||||
jmp [edi] // unmap ourselves via escape hatch, then goto entry
|
/*notrack*/ jmp [edi] // unmap ourselves via escape hatch, then goto entry
|
||||||
|
|
||||||
section SYSCALLS
|
section SYSCALLS
|
||||||
// Sometimes linux enforces page-aligned address
|
// Sometimes linux enforces page-aligned address
|
||||||
|
|||||||
@ -289,27 +289,31 @@ make_hatch_i386(
|
|||||||
unsigned frag_mask
|
unsigned frag_mask
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
char *hatch = 0;
|
unsigned *hatch = 0;
|
||||||
|
unsigned code[2] = {
|
||||||
|
0x586180cd, // int #0x80; popa; pop %eax
|
||||||
|
0x90e0ff3e, // notrack jmp *%eax; nop
|
||||||
|
}
|
||||||
DPRINTF("make_hatch %%p %%p %%x\\n", phdr, next_unc, frag_mask);
|
DPRINTF("make_hatch %%p %%p %%x\\n", phdr, next_unc, frag_mask);
|
||||||
if (phdr->p_type==PT_LOAD && phdr->p_flags & PF_X) {
|
if (phdr->p_type==PT_LOAD && phdr->p_flags & PF_X) {
|
||||||
next_unc += phdr->p_memsz - phdr->p_filesz; // Skip over local .bss
|
next_unc += phdr->p_memsz - phdr->p_filesz; // Skip over local .bss
|
||||||
frag_mask &= -(long)next_unc; // bytes left on page
|
frag_mask &= -(long)next_unc; // bytes left on page
|
||||||
unsigned /*const*/ escape = 0xc36180cd; // "int $0x80; popa; ret"
|
if (sizeof(code) <= frag_mask) {
|
||||||
if (4 <= frag_mask) {
|
hatch = (unsigned *)next_unc;
|
||||||
hatch = next_unc;
|
hatch[0] = code[0];
|
||||||
*(long *)&hatch[0] = escape;
|
hatch[1] = code[1];
|
||||||
}
|
}
|
||||||
else { // Does not fit at hi end of .text, so must use a new page "permanently"
|
else { // Does not fit at hi end of .text, so must use a new page "permanently"
|
||||||
unsigned long fdmap = upx_mmap_and_fd((void *)0, sizeof(escape), nullptr);
|
unsigned long fdmap = upx_mmap_and_fd((void *)0, sizeof(code), nullptr);
|
||||||
unsigned mfd = -1+ (0xfff& fdmap);
|
unsigned mfd = -1+ (0xfff& fdmap);
|
||||||
write(mfd, &escape, sizeof(escape));
|
write(mfd, &code, sizeof(code));
|
||||||
hatch = mmap((void *)(fdmap & ~0xffful), sizeof(escape),
|
hatch = mmap((void *)(fdmap & ~0xffful), sizeof(code),
|
||||||
PROT_READ|PROT_EXEC, MAP_PRIVATE, mfd, 0);
|
PROT_READ|PROT_EXEC, MAP_PRIVATE, mfd, 0);
|
||||||
close(mfd);
|
close(mfd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DPRINTF("hatch=%%p\\n", hatch);
|
DPRINTF("hatch=%%p\\n", hatch);
|
||||||
return hatch;
|
return (char *)hatch;
|
||||||
}
|
}
|
||||||
#elif defined(__arm__) /*}{*/
|
#elif defined(__arm__) /*}{*/
|
||||||
extern unsigned get_sys_munmap(void);
|
extern unsigned get_sys_munmap(void);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user