背景/我想要完成的事情的解釋
我目前正在從事一個小型惡意軟體分析專案,并正在嘗試實作我使用Unicorn撰寫的字串解密器。為了精簡內容并使代碼更易于查看,我在下面從我的較大代碼庫中制作了一個較小的示例。
我正在做的是提取代表小字串解密例程的 x86 片段。有一系列 mov 指令最終被異或產生一個明文字串。我已經注釋掉了應該產生的字串值。在以下示例中,模擬了未注釋的 X86_CODE64 指令,但僅在hpe.com我從堆疊地址中讀取時才會產生結果。(提示:要查看輸出,請在 上運行字串asdf.txt)我希望看到apple.com和hpe.com
題
根據下面的代碼,我做錯了什么/根本沒有做會導致以下代碼片段無法正確解密字串?
免責宣告:這是我第一次使用獨角獸,所以如果我表達不清楚或解釋有困難,我提前道歉!
#!/usr/bin/python
from __future__ import print_function
from unicorn import *
from unicorn.x86_const import *
# code to be emulated
# Strings should include apple.com and hpe.com
X86_CODE64 = b'\xc7D$<\xa9GY\x01\xc7D$@\xa2XQ/\x8bD$<\x8aD$8\x84\xc0u\x19H\x8b\xcb\x8bD\x8c<5\xc17</\x89D\x8c<H\xff\xc1H\x83\xf9\x02r\xeaE3\xc0H\x8dT$<H\x8b\xcf\xe8<\xd2\xfe\xff\x88]\xa4\xc7E\xa8\x86/\x00v\xc7E\xac\x82q\x13u\xc7E\xb0\x8a_p\x1a\x8bE\xa8\x8aE\xa4\x84\xc0u\x19H\x8b\xcb\x8bD\x8d\xa85\xe7_p\x1a'
# Strings should be svchost.exe
#X86_CODE64 = b"\xba\xe7_p\x1a\xc7D$|\x94)\x13r\xc7E\x80\x88,\x044\xc7E\x84\x82'\x15:\x89U\x88\x8bD$|\x8aD$x\x84\xc0u\x16H\x8b\xcf\x8bD\x8c|3\xc2"
# Strings should be apple.com
#X86_CODE64 = b'\xc7E\xa8\x86/\x00v\xc7E\xac\x82q\x13u\xc7E\xb0\x8a_p\x1a\x8bE\xa8\x8aE\xa4\x84\xc0u\x19H\x8b\xcb\x8bD\x8d\xa85\xe7_p\x1a'
# Set up Unicorn
ADDRESS = 0x10000000
STACK_ADDRESS = 0x90000
mu = Uc(UC_ARCH_X86, UC_MODE_64)
mu.mem_map(ADDRESS, 4 * 1024 * 1024)
mu.mem_map(STACK_ADDRESS, 4096*10)
# Write code to memory
mu.mem_write(ADDRESS, X86_CODE64)
# Initialize Stack for functions
mu.reg_write(UC_X86_REG_ESP, STACK_ADDRESS 4096)
mu.reg_write(UC_X86_REG_EDX, 0x0000)
# Run the code
try:
mu.emu_start(ADDRESS, ADDRESS len(X86_CODE64), timeout=10000)
except UcError as e:
pass
#a = mu.mem_read(ADDRESS, 4 * 1024 * 1024)
#print(a)
b = mu.mem_read(STACK_ADDRESS, 4096*10)
with open('asdf.txt', 'ab') as fp:
fp.write(b)
uj5u.com熱心網友回復:
這段代碼幾乎沒有問題。
pass首先,您可能永遠不想通過except至少在頂層寫入來吞下所有例外。至少為了知道是否發生了任何意外情況而將它們寫入控制臺會很好。如果你這樣做,你會注意到獨角獸Invalid memory fetch (UC_ERR_FETCH_UNMAPPED)在代碼執行期間拋出了一個。
如果您分析位元組,您會注意到在第一個代碼中間有一個奇怪的呼叫
40: e8 3c d2 fe ff call 0xfffffffffffed281
這個呼叫是在解密之后hpe.com并且 unicorn 停止執行代碼并且永遠不會到達代碼的第二部分。在 unicorn 中可能有更好的方法來處理這個問題,但現在讓我們只nop呼叫(用 5x 替換 5 個位元組\x90)。這仍然不會產生預期的apple.com字串,因為此代碼有更多問題。第二部分(通話后)沒有使用RSP,但RBP您沒有在代碼中設定它。
所以我們需要補充一點:
mu.reg_write(UC_X86_REG_EBP, STACK_ADDRESS 4096)
這是另一個問題。您正在為 64 位設定獨角獸,但您初始化了 32 位暫存器 - ESP, EDX. 這是故意的嗎?在您的情況下,這可能不是問題,但您可能應該初始化 64 位 regs。
添加RBP設定為某個堆疊地址后,您仍然不會看到第二個字串,因為代碼有點太早了。最后的指令是read & xor
6a: 8b 44 8d a8 mov eax,DWORD PTR [ebp ecx*4-0x58]
6e: 35 e7 5f 70 1a xor eax,0x1a705fe7
但是沒有存盤,沒有增量到下一部分,也沒有回圈。
也許你復制的位元組太少。如果我們這樣添加那些缺失的位元組:89448da8for store ( mov DWORD PTR [rbp rcx*4-0x58],eax)、48ffc1for inc rcx、4883f903forcmp rcx, 0x3和最后72eafor jb -0x16。
所以總的來說,你的第一個代碼錯過了以下位元組 89448da848ffc14883f90372ea( nop the call),并且
? python3 program.py
? 字串 asdf.txt
apple.com
hpe.com
你得到了預期的結果。
簡要檢查了第二個和第三個代碼,它似乎沒有call,但它們也缺少商店、公司和回圈部分。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/437332.html
