【问题标题】:Self modifying algorithms with Virtualprotect problems具有 Virtualprotect 问题的自修改算法
【发布时间】:2011-01-30 11:05:03
【问题描述】:

我在使用 Windows 的 Virtualprotect() api 时遇到问题。 我接到了一个学校的作业,我的老师告诉我们,在过去记忆稀缺且成本高昂的时候。程序员必须创建可以动态修改自身以节省内存的高级算法。所以你有它,我们现在必须编写这样一个算法,它不一定是有效的,但它必须修改自己。

所以我开始做这件事,我认为在寻求任何帮助之前我已经做到了。

我的程序是这样工作的:

我有一个函数和一个带有内置堆栈溢出的循环。堆栈被循环期间构造的代码所在的内存位置的地址溢出。控制权被传递给内存中的代码。代码加载一个 dll 然后退出,但在退出之前它必须修复循环。这是我们赋值的条件之一,必须恢复原始循环中更改的所有内容。

问题是我没有对循环的写访问权限,只有 READ_EXECUTE,所以我想改变我的访问权限,我使用 virtualprotect。但是那个函数返回了一个错误:

ERROR_NOACCESS,关于这个错误的文档很简陋,windows只说:Invailid access to memory address。自从我想首先更改访问权限以来,哪些数字。那么有什么问题呢?这是在内存中构建的代码: 我的代码中所有数据的名字有点模糊,所以提供了几个cmets

Size1: 
TrapData proc

jmp pLocals
LocalDllName db 100 dup(?)         ; name of the dll to be called ebx-82h
RestoreBuffer db 5 dup(?)          ; previous bytes at the overflow location
LoadAddress dd 0h    ; ebx - 19h   ; address to kernel32.loadlibrary
RestoreAddress dd 0h ; ebx - 15h   ; address to restore (with the restore buffer)
AddressToRestoreBuffer dd 0h ; ebx - 11h ; obsolete, I don't use this one
AddressToLea dd 0h  ; ebx - 0Dh          Changed, address to kernel32.virutalprotect
AddressToReturnTo dd 0h ; ebx - 9h       address to return execution to(the same as RestoreAddress
pLocals: 


call Refpnt
Refpnt: pop ebx    ; get current address in ebx

push ebx
mov eax, ebx

sub ebx, 82h
push ebx     ; dll name

sub eax, 19h          ; load lib address
mov eax, [eax]
call eax       


pop ebx         ; Current address
push ebx


;BOOL WINAPI VirtualProtect(
;  __in   LPVOID lpAddress,
;  __in   SIZE_T dwSize,
;  __in   DWORD flNewProtect,
;  __out  PDWORD lpflOldProtect
;);

mov eax, ebx
mov esi, ebx

sub eax, 82h
push eax            ; overwrite the buffer containing the dll name, we don't need it anymore
push PAGE_EXECUTE_READWRITE
push 5h
sub esi, 15h
mov esi, [esi]
push esi
sub ebx, 0Dh
mov ebx, [ebx]
call ebx        ; Returns error 998 ERROR_NOACCESS (to what?)

pop ebx
push ebx


sub ebx, 1Eh
mov eax, ebx    ; restore address buffer pointer

pop ebx
push ebx

sub ebx, 15h    ; Restore Address
mov ebx, [ebx]
xor esi, esi    ; counter to 0

@0:

push eax

mov al, byte ptr[eax+esi] 
mov byte ptr[ebx+esi], al

pop eax

inc esi
cmp esi, 5
    jne @0

pop ebx
sub ebx, 9h
mov ebx, [ebx]
push ebx    ; address to return to
ret

Size2: 

那怎么了? 你们能帮帮我吗?

编辑,工作代码:

Size1: 


jmp pLocals
LocalDllName db 100 dup(?)
RestoreBuffer db 5 dup(?)
LoadAddress dd 0h    ; ebx - 19h
RestoreAddress dd 0h ; ebx - 15h
AddressToRestoreBuffer dd 0h ; ebx - 11h
AddressToLea dd 0h  ; ebx - 0Dh
AddressToReturnTo dd 0h ; ebx - 9h
pLocals: 


call Refpnt
Refpnt: pop ebx    ; get current address in ebx

push ebx
mov eax, ebx

sub ebx, 82h
push ebx     ; dll name

sub eax, 19h          ; load lib address
mov eax, [eax]
call eax       


pop ebx         ; Current address
push ebx


;BOOL WINAPI VirtualProtect(
;  __in   LPVOID lpAddress,
;  __in   SIZE_T dwSize,
;  __in   DWORD flNewProtect,
;  __out  PDWORD lpflOldProtect
;);

mov esi, ebx

push 0
push esp
push PAGE_EXECUTE_READWRITE
push 5h
sub esi, 15h
mov esi, [esi]
push esi
sub ebx, 0Dh
mov ebx, [ebx]
call ebx

pop ebx
pop ebx
push ebx


sub ebx, 1Eh
mov eax, ebx    ; restore address buffer pointer

pop ebx
push ebx

sub ebx, 15h    ; Restore Address
mov ebx, [ebx]
xor esi, esi    ; counter to 0

@0:

push eax

mov al, byte ptr[eax+esi] 
mov byte ptr[ebx+esi], al

pop eax

inc esi
cmp esi, 5
    jne @0

pop ebx
sub ebx, 9h
mov ebx, [ebx]
push ebx    ; address to return to
ret


Size2: 

也许有点草率,但我不重要;)

【问题讨论】:

  • 关于编写“sploit 代码”的课程。不错。

标签: windows winapi assembly memory-management


【解决方案1】:

您正试图让VirtualProtectlpflOldProtect 写入只读内存位置,即您当前的代码部分,这是您首先要取消保护的部分!我猜这就是给你ERROR_NO_ACCESS的原因。由于您无论如何都在使用堆栈,所以让它将lpflOldProtect 写入堆栈位置。

【讨论】:

  • 嘿。既然你提到了它。这很可能是我的问题,我要试试看,我只需要传递一个指向堆栈的指针,对吗?
【解决方案2】:

这不像过去那么容易了;用于暗示执行访问的读访问,并且很多内存映射被映射为可写。

如今,如果有许多(任何?)内存映射既可写 可执行,我会感到惊讶。 (支持 PAE 的现代 CPU 甚至足以让 32 位内核提供不可执行但可读的映射。)

我想说,首先,找到一个较旧的 Windows 系统,Win2k 或更早版本,然后开始尝试解决这个问题。 :)

编辑:哦!我以为加载 DLL 失败了。干得好。 :)

“恢复循环”是什么意思?由于您破坏了堆栈以跳转到您的代码,因此您并没有真正破坏循环的文本段,您只是在堆栈上乱涂乱画。您可以在循环之前插入另一个函数,然后从 dll 返回到调用循环的函数。 (您从循环中“返回”到注入的代码中,因此如果不为其构建假堆栈框架,就无法返回到循环中;返回前一个函数似乎比构建假堆栈框架更容易。)

【讨论】:

  • 除了那不能解决我的问题,唯一剩下的问题是无法恢复循环。其余的工作正常。
猜你喜欢
  • 2015-06-11
  • 2023-04-05
  • 2021-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-23
相关资源
最近更新 更多