如何在 Windows XP/7 机器上找到内存中的字节序列?

发布于 2024-11-03 06:48:23 字数 964 浏览 1 评论 0 原文

问题:我正在为学校开发一个项目(我的选择),它是一个程序加载器/DLL 注入器,我最初发现的想法 此处,进行修改以满足我的需要,并将 DLL 的 ASM 部分转换为扩展 ASM,该扩展 ASM 将使用 GCC 而不是 Visual Studio 进行编译。我不是在控制台窗口中打印弹球得分,而是加载一个我编写的程序,该程序接受用户的输入并将其写入文件。加载程序注入一个 DLL,其中包含一个函数,该函数将以前发送到文件的用户输入重定向到消息框,并将我自己的字符串写入该文件。

它可以在我的机器上运行,但是,我担心平台切换,因为我的教授必须在她的机器上编译工作,因此地址 0x004014A6 有可能,该地址当前包含以下指令: CALL 将该字符串写入文件(实际代码是:ofile << user_input;)不会包含任何接近该字符串的内容在另一台机器上编译,但仍然会调用该函数,将字符串写入文件。

我想要做的是动态确定该地址是什么,而不是对地址进行硬编码。我想我可以通过在被调用的函数上使用 GetProcAddress 来获取地址,然后创建一个数组来保存表示 CALL 的字节,并在内存中逐字节搜索我希望在某个地方找到要拨打的电话,获取地址,然后从那里开始工作。

但我不知道具体该怎么做。

主要问题:如何扫描内存地址范围并将内容与数组元素进行比较?

换句话说,我想在 DLL 中包含一个函数,该函数读取内存中任意地址的字节并将其与预期序列进行比较。如何才能任意读取某个进程内内存地址的内容呢?

怀疑:我需要知道原始程序执行的起始地址和结束地址。如何获取起始地址和结束地址之间的范围? (这似乎是这里真正的障碍。我可能只能让其余的人知道如何获取进程的开始和结束地址。)

Problem: I'm working on a project for school (my choice) which is a program loader/DLL injector, the idea of which I initially found here, modified to suit my needs, and converted the ASM portions of the DLL to extended ASM that will compile with GCC instead of Visual Studio. Rather than do the pinball score print in a console window thing, I'm loading a program I wrote that takes input from a user and writes it to a file. The loader injects a DLL with a function in it that redirects user input, formerly destined for a file, to a messagebox, and will write my own string to the file.

It works on my machine, however, I have concerns about platform switching because my professor has to compile the work on her machine, so it is possible that the address 0x004014A6, which currently contains the instruction to
CALL <some address> which writes that string to a file(the actual code is: ofile << user_input;) won't contain anything close to that when compiled on another machine, but will still have a call to that function that writes a string to a file.

What I want to do is dynamically determine what that address will be, as opposed to hardcoding the address. I think I can do this by using GetProcAddress on the function that gets called to get the address, then create an array to hold the bytes representing CALL <that function>, and search byte by byte in memory somewhere around where I expect to find that call to be made, take the address, and work from there.

I don't know exactly how to do that, though.

MAIN QUESTION: How can I scan a range of memory addresses and compare the contents to elements of an array?

Put another way, I want to include in my DLL a function that reads bytes at an arbitrary address in memory and compares it to an expected sequence. How can I just arbitrarily read contents of memory addresses within a certain process?

Suspicions: I'll need to know the starting and ending addresses where execution of the original program takes place. How can I get the range between starting and ending addresses? (This seems like the real hurdle here. I can probably get the rest knowing only how to obtain the processes beginning and ending addresses.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

终遇你 2024-11-10 06:48:23

除非您的目标程序版本很快就会改变,否则您可以使用 VA(虚拟地址) = RVA(相对虚拟地址) + 模块基本加载地址(可以通过 GetModuleHandle 获取)来得到一个在不同系统下都不会失败的地址。如果版本确实发生变化,那么您将查看签名扫描仪。然而,它们并不是万无一失的,因为您扫描的模式可能会从一个构建到下一个构建发生根本性的变化。所需的任何范围数据都可以从目标应用程序的 PE 中获取,然后可以使用这些数据临时将读取权限应用于 .code 部分,从而允许您高效地循环它(效率不太高)是使用ReadProcessMemory)。这是一个小的 sigscanner 库,再往下还有一个简单 sig 扫描器的源链接: http://www.blizzhackers.cc/viewtopic.php?f=182&t=478228&sid=55fc9a949aa0beb2ca2fb09e933210de

Unless the version of the program is your targeting is gonna change soon, you can use VA(virtual address) = RVA(relative virtual address) + module Base load address(which can be gotten with GetModuleHandle) to get an address that won't fail under different systems. If the version does change, then your looking at a signature scanner. They aren't foolproof however, as the patterns your scanning for can radically change from one build to the next. Any range data needed can be gotten from the PE of the targetted app, that can then be used to temporarily apply read privilages to the .code section, allowing you to loop through it efficiently(the not so efficient was is to use ReadProcessMemory). Here is a small sigscanner lib, farther down is also a link to source for a simple sig scanner: http://www.blizzhackers.cc/viewtopic.php?f=182&t=478228&sid=55fc9a949aa0beb2ca2fb09e933210de

っ〆星空下的拥抱 2024-11-10 06:48:23

如果您使用 Python,也许 ptrace 可以提供帮助。它是跨平台的,可以通过 pip 安装。这是我在这里抓取的 unix 代码片段: http://sixserv.org/2010/07/26/memory-debugging-or-a-universal-game-trainer-with-python-and-ptrace/

def search_memory_locations(pid, max_memory, search_value):
    child_pid = os.fork()
    if child_pid == 0: # search within forked process:
        locations = list()
        prev_locations = read_locations()

        dbg = PtraceDebugger()
        process = dbg.addProcess(pid, False)
        memory_mappings = readProcessMappings(process)

        print "\x1B[?25l", # deactivate cursor (^_^)
        for memory_mapping in memory_mappings:
            # only search in read/writable memory areas within range...
            if "rw" in memory_mapping.permissions and memory_mapping.end <= max_memory:
                for loc in range(memory_mapping.start, memory_mapping.end):
                    value = process.readBytes(loc, 1)
                    if value[0] == search_value:
                        print "search memory area[0x%08X-0x%08X] address[0x%08X] value[0x%02X (%03d)]   \r" % (memory_mapping.start, memory_mapping.end, loc, ord(value), ord(value)),

                        if prev_locations and len(prev_locations) > 0 and not loc in prev_locations:
                            continue # skip prev not found locations

                        locations.append(loc)
        print "\x1B[?25h", # activate cursor
        dbg.quit()
        write_locations(locations)
        sys.exit()

    return child_pid # don't really need this

如果您使用C/C++,这是我之前从 ITH 使用的一个特定于 Windows 的函数 (http://code.google.com/p/interactive-text-hooker/):

DWORD SearchPattern(DWORD base, DWORD base_length, LPVOID search, DWORD search_length) //KMP
{
    __asm
    {
        mov eax,search_length
alloc:
        push 0
        sub eax,1
        jnz alloc

        mov edi,search
        mov edx,search_length 
        mov ecx,1
        xor esi,esi
build_table:
        mov al,byte ptr [edi+esi]
        cmp al,byte ptr [edi+ecx]
        sete al
        test esi,esi
        jz pre
        test al,al
        jnz pre
        mov esi,[esp+esi*4-4]
        jmp build_table
pre:
        test al,al
        jz write_table
        inc esi
write_table:
        mov [esp+ecx*4],esi

        inc ecx
        cmp ecx,edx
        jb build_table

        mov esi,base
        xor edx,edx
        mov ecx,edx
matcher:
        mov al,byte ptr [edi+ecx]
        cmp al,byte ptr [esi+edx]
        sete al
        test ecx,ecx
        jz match
        test al,al
        jnz match
        mov ecx, [esp+ecx*4-4]
        jmp matcher
match:
        test al,al
        jz pre2
        inc ecx
        cmp ecx,search_length
        je finish
pre2:
        inc edx
        cmp edx,base_length //search_length
        jb matcher
        mov edx,search_length
        dec edx
finish:
        mov ecx,search_length
        sub edx,ecx
        lea eax,[edx+1]
        lea ecx,[ecx*4]
        add esp,ecx
    }
}

If you are using Python, maybe ptrace could help. It is cross-platfrom, and could be installed from pip. Here's a code snip for unix that I grabbed here: http://sixserv.org/2010/07/26/memory-debugging-or-a-universal-game-trainer-with-python-and-ptrace/

def search_memory_locations(pid, max_memory, search_value):
    child_pid = os.fork()
    if child_pid == 0: # search within forked process:
        locations = list()
        prev_locations = read_locations()

        dbg = PtraceDebugger()
        process = dbg.addProcess(pid, False)
        memory_mappings = readProcessMappings(process)

        print "\x1B[?25l", # deactivate cursor (^_^)
        for memory_mapping in memory_mappings:
            # only search in read/writable memory areas within range...
            if "rw" in memory_mapping.permissions and memory_mapping.end <= max_memory:
                for loc in range(memory_mapping.start, memory_mapping.end):
                    value = process.readBytes(loc, 1)
                    if value[0] == search_value:
                        print "search memory area[0x%08X-0x%08X] address[0x%08X] value[0x%02X (%03d)]   \r" % (memory_mapping.start, memory_mapping.end, loc, ord(value), ord(value)),

                        if prev_locations and len(prev_locations) > 0 and not loc in prev_locations:
                            continue # skip prev not found locations

                        locations.append(loc)
        print "\x1B[?25h", # activate cursor
        dbg.quit()
        write_locations(locations)
        sys.exit()

    return child_pid # don't really need this

If you are using C/C++, here's a function specific for Windows that I used before from ITH (http://code.google.com/p/interactive-text-hooker/):

DWORD SearchPattern(DWORD base, DWORD base_length, LPVOID search, DWORD search_length) //KMP
{
    __asm
    {
        mov eax,search_length
alloc:
        push 0
        sub eax,1
        jnz alloc

        mov edi,search
        mov edx,search_length 
        mov ecx,1
        xor esi,esi
build_table:
        mov al,byte ptr [edi+esi]
        cmp al,byte ptr [edi+ecx]
        sete al
        test esi,esi
        jz pre
        test al,al
        jnz pre
        mov esi,[esp+esi*4-4]
        jmp build_table
pre:
        test al,al
        jz write_table
        inc esi
write_table:
        mov [esp+ecx*4],esi

        inc ecx
        cmp ecx,edx
        jb build_table

        mov esi,base
        xor edx,edx
        mov ecx,edx
matcher:
        mov al,byte ptr [edi+ecx]
        cmp al,byte ptr [esi+edx]
        sete al
        test ecx,ecx
        jz match
        test al,al
        jnz match
        mov ecx, [esp+ecx*4-4]
        jmp matcher
match:
        test al,al
        jz pre2
        inc ecx
        cmp ecx,search_length
        je finish
pre2:
        inc edx
        cmp edx,base_length //search_length
        jb matcher
        mov edx,search_length
        dec edx
finish:
        mov ecx,search_length
        sub edx,ecx
        lea eax,[edx+1]
        lea ecx,[ecx*4]
        add esp,ecx
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文