• 也发个内嵌ASM,可用且可用!


            图省事,上网上找这个代码,我去,没烦死,五花八门,就是没有能运行的。可惜,笔记本报废的时候把硬盘嚼的烂烂的,然后之后最后还是狠下心来为了测试自己写了。

    实现的思路挺多的,都能搞定这个事情。

    1、callwindowproc额好像是这个名字,而且这个代码我硬盘上也有,但是明显慢。

         原理就是这个API接收一个地址并不检查就运行了。于是可以在内存里面构建一串ASM代码。

         用这个方法需要注意的是要把API函数本身的几个参数弹了,大概是push eax 然后4个pop ecx 再pop eax然后是我们的代码。

    2、线程、远线程

         这个就是线程启动的时候可以传入地址,然后就运行了,不过也涉及到一些东西。不说了这个。

    3、使用委托

         这个就是我们要介绍的东西了,实现方式也挺多的。像有的去声明一个实际函数,然后往里面写ASM,再去调用相应的委托。这里我们介绍的是GetDelegateForFunctionPointer方法以及相应的一些步骤等:

    1、准备工作:

    API声明、委托声明:

        Private Declare Function VirtualProtect Lib "kernel32.dll" (ByVal lpAddress As IntPtr, ByVal dwSize As Integer, ByVal flNewProtect As Integer, ByRef lpflOldProtect As Integer) As Integer
    
        Delegate Function subarg(arg1 As Integer, arg2 As Integer) As Integer
    
        Dim dlgt As subarg

    感觉不用解释,就是API,subarg是函数的形式,dlgt是实例化的subarg。只需要注意dlgt这个要全局,不然GC说不定啥时候就给你把委托捣鼓没了。

    2、准备工作

    O(∩_∩)O~

    为了方便用字符串形式表示ASM代码(用BYTE数组也行,可是不太舒服)写一个函数:

        Private Function Str2Bytes(str As String) As Byte()
            Dim i As Integer
            Dim assemblyCode As String
            assemblyCode = str.Replace(Space(1), String.Empty)
            Dim AssemblyValue(Len(assemblyCode) \ 2 - 1) As Byte
            For i = 1 To Len(assemblyCode) Step 2
                AssemblyValue(i \ 2) = Val("&H" & Mid(assemblyCode, i, 2))
            Next
            Return AssemblyValue
        End Function

    这个更没什么好说的,就是为了用字符串表示,然后用空格啥的分开看起来清晰。

    3、准备工作

    我就不怕鸡蛋。写函数了,我加了个按钮。

        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
            Dim bs() = Str2Bytes(asmStr)
            Dim ptr As IntPtr = Marshal.AllocHGlobal(bs.Length)
            Dim lpflOldProtect As Integer
            VirtualProtect(ptr, 1, &H40, lpflOldProtect)    'rw+e
            Marshal.Copy(bs, 0, ptr, bs.Length)
            dlgt = Marshal.GetDelegateForFunctionPointer(ptr, GetType(subarg))
            MsgBox("当前可在所显示地址上下断点,观察函数调用情况。" & Hex(ptr.ToInt32), MsgBoxStyle.OkOnly, "函数汇编地址")
            Dim t As Integer = My.Computer.Clock.TickCount
            Dim i, r As Integer, n As Integer = 10000000
            For i = 0 To n - 1
                r = dlgt.Invoke(1, 2)
            Next
            Debug.Print(r & " " & n \ (My.Computer.Clock.TickCount - t))
            Marshal.FreeHGlobal(ptr)
        End Sub

    简单解释一下,生成之后,一定要改一下内存属性,一般就是读写+运行了,反正也不恢复了,就不记录原始内存页属性,但是最好回收那块内存。

    4、准备工作

    - -!!!

    其实前面的和绝大多数代码还是一样的,然后就是ASM了。这才是大头戏。一般来说,没有一点ASM造诣这个内嵌ASM不太好办,其实我就没有多点,知道的指令不超过5条,都是现用现查。如果自己写有问题,那么可以用VC写出来函数,然后用OD,IDA啥的看看,函数是什么样的作为参考。不过这样做完全照搬一般不行,因为那个函数里面有一些额外的东东。比较“正统”的做法应该是用ASM编程工具写代码然后链接编译,我一般会使用VC的内嵌汇编,因为不会用其他工具,连从哪打开都不知道- -!

    这里我写了一个简单的函数,就是参数1 、 参数2作差:

        Dim asmStr As String = "55 8BEC" & _
                               "8B45 08 2B45 0C" & _
                               "5D C2 08 00"

    仔细分析一下这个函数的由来:

    A、用VC.NET建立一个MFC DLL,共享MFC那个,工程名subarg。(其实都无所谓了,差不多的事)

    B、在subarg.cpp里面写上个函数,直接return a-b就行了。(复制上面的注释,稍微一改)

    C、更改配置为release生成,然后OD或者IDA。分析代码,EAX做返回值,可以看到一些关键代码(IDA复制的,a,b其实是它的一种表示形式,如果是od就会看到mov sub那里分别写8,c):

    a= dword ptr  8

    b= dword ptr  0Ch

    push    ebp

    mov     ebp, esp

    ……

    mov     eax, [ebp+a]
    sub     eax, [ebp+b]

    ……

    其实这就是了。上面还有一些寄存器的清理,用来做了一些别的事情,实际上我们就用一个EAX,所以其他没管。可能下面还有一些东西,但是EAX值就到这里了。当然,返回那里还清理了一些东西。但是为什么我的代码里面没有呢,其实用ASM编程工具写一个子函数看一下就知道了,这个子函数不用恢复。ret 8的意思就是说舍弃2个4,因为有2个参数,如果1个就是ret 4,如果3个就是……ret c

    所以我们的函数全貌如下:

       push ebp           
       mov ebp,esp      


       mov eax,[ebp+8]   
       sub eax,[ebp+c]    


       pop ebp       
       RET 8            

    直接从DIA里面抄就行,其实要是用OD,就直接打进去这些汇编就行了,CE、xuer什么都行。

    最终的结果就是:

        Dim asmStr As String = "55 8BEC" & _
                               "8B45 08 2B45 0C" & _
                               "5D C2 08 00"


    一行对应上面一段。全部代码都在上面了,下面附一份全的:

    View Code
    Imports System.Runtime.InteropServices
    
    Public Class Form1
        Private Declare Function VirtualProtect Lib "kernel32.dll" (ByVal lpAddress As IntPtr, ByVal dwSize As Integer, ByVal flNewProtect As Integer, ByRef lpflOldProtect As Integer) As Integer
    
        '作为被调函数处理。因为参数是2个,所以舍弃8位。
        'push ebp           55
        'mov ebp,esp        8b ec
        '============实际函数============
        'mov eax,[ebp+8]    8b45 08
        'sub eax,[ebp+c]    2b45 0c
        '================================
        'pop ebp            5d
        'RET 8              c2 08 00
    
        Dim asmStr As String = "55 8BEC" & _
                               "8B45 08 2B45 0C" & _
                               "5D C2 08 00"
        Delegate Function subarg(arg1 As Integer, arg2 As Integer) As Integer
    
        Dim dlgt As subarg
    
        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
            Dim bs() = Str2Bytes(asmStr)
            Dim ptr As IntPtr = Marshal.AllocHGlobal(bs.Length)
            Dim lpflOldProtect As Integer
            VirtualProtect(ptr, 1, &H40, lpflOldProtect)    'rw+e
            Marshal.Copy(bs, 0, ptr, bs.Length)
            dlgt = Marshal.GetDelegateForFunctionPointer(ptr, GetType(subarg))
            MsgBox("当前可在所显示地址上下断点,观察函数调用情况。" & Hex(ptr.ToInt32), MsgBoxStyle.OkOnly, "函数汇编地址")
            Dim t As Integer = My.Computer.Clock.TickCount
            Dim i, r As Integer, n As Integer = 10000000
            For i = 0 To n - 1
                r = dlgt.Invoke(1, 2)
            Next
            Debug.Print(r & " " & n \ (My.Computer.Clock.TickCount - t))
            Marshal.FreeHGlobal(ptr)
        End Sub
    
        Private Function Str2Bytes(str As String) As Byte()
            Dim i As Integer
            Dim assemblyCode As String
            assemblyCode = str.Replace(Space(1), String.Empty)
            Dim AssemblyValue(Len(assemblyCode) \ 2 - 1) As Byte
            For i = 1 To Len(assemblyCode) Step 2
                AssemblyValue(i \ 2) = Val("&H" & Mid(assemblyCode, i, 2))
            Next
            Return AssemblyValue
        End Function
    
    
    End Class
  • 相关阅读:
    ulimit
    python3.7安装Scrapy
    用VS2013写第一个汇编语言程序
    螺旋矩阵问题
    Java Web Pro与apache tomcat初始化关联
    记一次m3u8多个视频文件合并为整体法四(未加密)
    记一次m3u8多个视频文件合并为整体法三(未加密)
    记一次m3u8多个视频文件合并为整体法二(未加密)
    记将m3u8多个视频文件合并为整体法一(未加密)
    c++给定字符分割
  • 原文地址:https://www.cnblogs.com/zcsor/p/2833209.html
Copyright © 2020-2023  润新知