可以使用哪些其他方法在可执行文件中查找文件路径?

逆向工程 视窗 ollydbg 字符串
2021-06-29 19:15:20

我正在破解我的库(Mirror's Edge)中的游戏以重新路由保存数据所在的位置。我已经在许多其他游戏中成功地做到了这一点,但这个让我难住了。通常,我从 HxD 开始并搜索标准或 unicode 字符串。如果我无法使用像 HxD 这样的简单程序找到我正在寻找的字符串,我就会转向更高级的程序,比如 OllyDbg。在 OllyDbg 中,我要么使用内存映射,要么在 CPU 窗口中搜索所有引用的字符串。游戏最初被混淆并有保护,但我已经(成功)删除了它。我无法使用我知道的任何方法找到字符串,是否有其他工具或选项可以使用 HxD 或 OllyDbg 来查找存储方式不同的字符串?

目前游戏将其数据保存在:

%USERPROFILE%\Documents\EA Games\Mirror's Edge
1个回答

有需要写入文件
API用于打开和写入文件的文档化API示例是文件打开 -> kernel32.CreateFile 文件写入 -> kernel32!WriteFile

这些 api 需要内核模式转换,它发生在 ntdll.NtCreateFile 和 ntdll!NtWriteFile

您可以在 ollydbg 中使用 ctrl+g 来跟踪这些 api 并在那里设置断点

假设你有一个文件打开一个文件写如下代码

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
void main(void) {
    char *foo = "lets open a file and write in it something\n";
    FILE *fp =NULL;    
    if((fp = fopen("c:\\somewrite.text" , "wb")) != NULL) {
        fwrite(foo,strlen(foo),1,fp);
        printf("we wrote this %s\n" , foo);
        fclose(fp);
    }
} 

在ollydbg v2.0中打开编译好的exe

ctrl+g -> ntdll.NtCreateFile -> follow -> f2-> f9

你应该在这里休息

CPU Stack
Address  Comments
ESP ==>  ; /RETURN to KERNELBASE.CreateFileW+1D1
ESP+4    ; |Arg1 = 26F614
ESP+8    ; |Arg2 = 40100080
ESP+C    ; |Arg3 = 26F5B8
ESP+10   ; |Arg4 = 26F5FC
ESP+14   ; |Arg5 = 0
ESP+18   ; |Arg6 = 80
ESP+1C   ; |Arg7 = 3
ESP+20   ; |Arg8 = 5
ESP+24   ; |Arg9 = 60
ESP+28   ; |Arg10 = 0
ESP+2C   ; \Arg11 = 0

ZwCreateFile记录为

NTSTATUS ZwCreateFile(
  _Out_    PHANDLE            FileHandle,
  _In_     ACCESS_MASK        DesiredAccess,
  _In_     POBJECT_ATTRIBUTES ObjectAttributes,
  _Out_    PIO_STATUS_BLOCK   IoStatusBlock,
  _In_opt_ PLARGE_INTEGER     AllocationSize,
  _In_     ULONG              FileAttributes,
  _In_     ULONG              ShareAccess,
  _In_     ULONG              CreateDisposition,
  _In_     ULONG              CreateOptions,
  _In_opt_ PVOID              EaBuffer,
  _In_     ULONG              EaLength
);

第三个参数是指向_OBJECT_ATTRIBUTES 的指针,它有一个成员 ObjectName,它是一个指向_UNICODE_STRING的指针

typedef struct _OBJECT_ATTRIBUTES {
  ULONG           Length;
  HANDLE          RootDirectory;
  PUNICODE_STRING ObjectName;
  ULONG           Attributes;
  PVOID           SecurityDescriptor;
  PVOID           SecurityQualityOfService;
}  OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;


typedef struct _UNICODE_STRING {
  USHORT Length;
  USHORT MaximumLength;
  PWSTR  Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

所以 0x26f5b8 是指向 OBJECT_ATTRIBUTES 的指针

CPU Dump
Address   Hex dump                                         ASCII
0026F5B8  18 00 00 00|00 00 00 00|F4 F5 26 00|42 00 00 00|        ôõ& B
0026F5C8  00 00 00 00|E0 F5 26 00|                             àõ&

此结构 0x0026f5f4 的第三个成员是指向 unicode 字符串的指针

CPU Dump
Address   Hex dump                                         ASCII
0026F5F4  2A 00 1A 02|88 99 40 00|                         * ˆ™@

宽字符缓冲区是 0x00409988

CPU Dump
Address   Hex dump                                         ASCII
00409988  5C 00 3F 00|3F 00 5C 00|63 00 3A 00|5C 00 73 00| \ ? ? \ c : \ s
00409998  6F 00 6D 00|65 00 77 00|72 00 69 00|74 00 65 00| o m e w r i t e
004099A8  2E 00 74 00|65 00 78 00|74 00 00 00|             . t e x t

您可以在转储中使用 follow 来跟踪并找到路径 您可以使用 ctrl+k 查看调用堆栈并定位可能在此之前操作或创建路径的函数

当您在转储窗口type ctrl+g and type in [[[esp+c]+8]+4] 尊重第三个参数 (esp+c) 中破坏此 API 时,您也可以将此快捷方式用于此特定功能,然后尊重第三个成员,然后尊重第二个成员