多线程逆向

发布时间 2023-10-13 20:28:19作者: ONE_ZJ

一.资料检索以及归纳

  1. XDBG调试时默认是只运行下断调试的线程 其它线程处于暂停挂起状态属于单线程调试。打开线程窗口可以查看线程挂起计数(+号 -号快捷键可以挂起恢复线程)双击线程可进入选择线程,如果要调试指定线程的话我的理解是应该在线程代码中下断(线程的各种系统 CALL),线程会自己断下。CE调试时是不挂起其它线程的。

  2. c当中创建新线程的函数为:CreateThread函数,下面是具体例子

    #include <windows.h>
    #include <stdio.h>
    
    // 线程函数
    DWORD WINAPI ThreadFunc(LPVOID lpParam) {
        printf("Hello, World from new thread!
    ");
        return 0;
    }
    
    int main() {
        HANDLE hThread; // 线程句柄
        DWORD dwThreadId; // 线程ID
    
        // 创建线程
        hThread = CreateThread(
            NULL,                   // default security attributes
            0,                      // use default stack size  
            ThreadFunc,             // thread function name
            NULL,                   // argument to thread function 
            0,                      // use default creation flags 
            &dwThreadId);           // returns the thread identifier 
    
        if (hThread == NULL) {
            printf("CreateThread failed, error %d
    ", GetLastError());
            return 1;
        }
    
        // 等待线程结束
        WaitForSingleObject(hThread, INFINITE);
    
        // 关闭线程句柄
        CloseHandle(hThread);
    
        return 0;
    }
    
    
  3. TEB (Thread Environment Block) 是 Windows 操作系统中的一个数据结构,用于存储线程本地存储的数据。每个线程都有自己的 TEB,包含了该线程所需的所有变量和函数调用的上下文信息。

    typedef struct _TEB {
        PVOID Reserved1[12];
        PPEB ProcessEnvironmentBlock;//重点关注该指针的内容
        PVOID Reserved2[399];
        BYTE Reserved3[1952];
        PVOID TlsSlots[64];
        BYTE Reserved4[8];
        PVOID Reserved5[26];
        PVOID ReservedForOle;
        PVOID Reserved6[4];
        PVOID TlsExpansionSlots;
    } TEB, *PTEB;
    Reserved1: 保留字段,不能被使用。
    ProcessEnvironmentBlock: 指向当前进程的环境块的指针,包含有关进程环境的信息。
    Reserved2: 保留字段,不能被使用。
    Reserved3: 保留字段,不能被使用。
    TlsSlots: 指向线程本地存储(TLS)中的插槽数组的指针,每个插槽用于存储一个特定的变量或数据结构。
    Reserved4: 保留字段,不能被使用。
    Reserved5: 保留字段,不能被使用。
    ReservedForOle: 保留字段,不能被使用。
    Reserved6: 保留字段,不能被使用。
    TlsExpansionSlots: 指向线程本地存储扩展槽的指针,用于支持扩展属性
    
  4. 多线程执行的时候线程的执行顺序是不确定的,这是由操作系统决定,线程的优先级只是决定CPU分配给该线程时间片的多少,不决定执行次序,优先级低的线程可能先执行。

二.思考记录

  1. 在xdbg当中可以通过查看线程窗口查看有关的线程内容,里面的线程有关信息。

  2. 找到创建进程的函数调用处,使用F8单步步过,然后过一段时间就可以在线程窗口找到该线程的有关信息。

  3. 针对多线程可以通过一个信号量实现多线程之间的同步,确保线程之间的执行顺序。

    例如:

    这里就是典型的通过全局变量dword_409804来判断应该执行哪个线程,当某个线程执行时先判断全局变量是否正确,如果不正确则sleep,等到下次cpu调用该线程时再判断是否相等,如果相等则执行。这个时候多线程就可以看成是一个线程。

    //线程1
     while ( dword_409804 != 1 )
      {
        Sleep(0x1F4u);
        sub_4015E0();
      }
    ...
    dword_409804 = 2;
    
    //线程2
     while ( dword_409804 != 2 )
        Sleep(0x1F4u);
    dword_409804n = 3;
    
  4. 多线程情况下,在创建了一个线程后,该线程会根据操作系统的调度自动执行,所以如果要分析不同线程的代码,那么就应该确定该线程执行的代码块,然后在该代码块处下断点分析,当该线程执行的时候,就可以停下来动态分析,所以最好还是先静态调试分析代码,然后再考虑应该如何动态分析。

三.参考文章

  1. [原创]样本分析中解决 ollydbg 多线程调试-软件逆向-看雪-安全社区|安全招聘|kanxue.com