Implemented indirect calls

This commit is contained in:
Eduard Urbach 2024-08-16 20:39:04 +02:00
parent 499fe8aec8
commit 34aeba740a
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
4 changed files with 45 additions and 5 deletions

View File

@ -1,7 +1,8 @@
package x64
// Call places the return address on the top of the stack and continues
// program flow at the new address. The address is relative to the next instruction.
// program flow at the new address.
// The address is relative to the next instruction.
func Call(code []byte, address uint32) []byte {
return append(
code,
@ -12,3 +13,18 @@ func Call(code []byte, address uint32) []byte {
byte(address>>24),
)
}
// CallAtAddress places the return address on the top of the stack and
// continues program flow at the address stored at the given memory address.
// The memory address is relative to the next instruction.
func CallAtAddress(code []byte, address uint32) []byte {
return append(
code,
0xFF,
0x15,
byte(address),
byte(address>>8),
byte(address>>16),
byte(address>>24),
)
}

View File

@ -111,6 +111,25 @@ func (a Assembler) Finalize() ([]byte, []byte) {
codePointers = append(codePointers, pointer)
case CALL_AT:
code = x64.CallAtAddress(code, 0x00_00_00_00)
size := 4
// label := x.Data.(*Label)
pointer := &Pointer{
Position: Address(len(code) - size),
OpSize: 2,
Size: uint8(size),
}
pointer.Resolve = func() Address {
destination := Address(0x1038)
distance := destination - (pointer.Position + Address(pointer.Size))
return Address(distance)
}
codePointers = append(codePointers, pointer)
case COMMENT:
continue

View File

@ -29,6 +29,7 @@ const (
// Control flow
CALL
CALL_AT
JE
JNE
JG
@ -54,6 +55,8 @@ func (m Mnemonic) String() string {
return "and"
case CALL:
return "call"
case CALL_AT:
return "call at"
case COMMENT:
return "comment"
case COMPARE:

View File

@ -48,8 +48,9 @@ func (r *Result) finalize() ([]byte, []byte) {
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[1], 0)
final.Syscall()
case "windows":
final.RegisterNumber(asm.MOVE, x64.RAX, 0)
final.Return()
final.RegisterNumber(asm.SUB, x64.RSP, 32+8)
final.RegisterNumber(asm.MOVE, x64.RCX, 0)
final.Label(asm.CALL_AT, "ExitProcess")
}
// This will place the main function immediately after the entry point
@ -70,8 +71,9 @@ func (r *Result) finalize() ([]byte, []byte) {
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[1], 1)
final.Syscall()
case "windows":
final.RegisterNumber(asm.MOVE, x64.RAX, 1)
final.Return()
final.RegisterNumber(asm.SUB, x64.RSP, 32+8)
final.RegisterNumber(asm.MOVE, x64.RCX, 1)
final.Label(asm.CALL_AT, "ExitProcess")
}
code, data := final.Finalize()