在开始使用TEB/PEB获取进程或线程ID之前,我想有必要解释一下这两个名词,PEB指的是进程环境块(Process Environment Block),用于存储进程状态信息和进程所需的各种数据。每个进程都有一个对应的PEB结构体。TEB指的是线程环境块(Thread Environment Block),用于存储线程状态信息和线程所需的各种数据。每个线程同样都有一个对应的TEB结构体。

PEB中包含了进程的代码、数据段指针、进程的环境变量、进程启动参数信息以及加载的dll信息等。PEB结构体中的FS段寄存器通常被设置为0x30,指向当前进程的PEB结构体。其他进程可以通过访问自己的PEB结构体来获取自己的状态和信息。

TEB中包含了线程的堆栈指针、TLS(线程本地存储)指针、异常处理链表指针、用户模式分页表指针等信息。TEB中的FS段寄存器通常被设置为fs:[0],指向当前线程的TEB结构体。其他线程可以通过访问自己的TEB结构体来获取自己的状态和信息。

在创建进程时,操作系统会为每个线程分配一个TEB(线程环境块),并且该环境块中FS段寄存器总是被设置为fs:[0]的位置上,也就是默认指向当前线程的TEB数据。因此,在进行代码分析时,可以通过通配符来找到TEB结构体的具体名称。

接着我们可通过dt -rv ntdll!_TEB命令,查询ntdll!_TEB结构,如下图所示,我们可以看到偏移为+0x018的位置就是TEB结构头指针,在该地址基础上向下偏移0x30就可以得到PEB(进程环境块)的基地址。

其中+0x000的位置指向了NT_TIB结构,+0x018指向NT_TIB结构TEB自身,+0x020+0x000指向的是当前进程的PID,+0x020+0x004则指向父进程的PPID,+0x030指向了PEB结构体,其他字段读者可自行查阅官方文档;

接着再来验证一下,首先偏移地址0x18是TEB结构基地址,也就是指向自身偏移fs:[0x18]的位置,而!teb地址加0x30正是PEB的位置,在teb的基础上加上0x30就可以得到PEB的基地址,拿到PEB基地址就可以干很多事了。

在线程环境块内,fs:[0x18]定位到TEB(线程环境块),加上0x20得到ClientId,此处存储的就是进程与线程ID的结构位置,通过+0x000可得到UniqueProcess也就是进程PID,通过+0x004可得到UniqueThread也就是线程TID,读者可输入如下所示的命令自行验证;

0:000> dd fs:[0x18]                                  # 找到TEB基地址
0053:00000018 0081e000 00000000 0000139c 0000194c
0053:00000028 00000000 0081e02c 0081b000 00000000 0:000> dt _teb 0081e000
ntdll!_TEB
+0x000 NtTib : _NT_TIB
+0x01c EnvironmentPointer : (null)
+0x020 ClientId : _CLIENT_ID # 将TEB+0x20定位到这里(进程与线程信息)
+0x028 ActiveRpcHandle : (null) 0:004> dt _CLIENT_ID 0081e000 # 查看进程详细结构
ntdll!_CLIENT_ID
+0x000 UniqueProcess : 0x00b3f774 Void # 获取进程PID
+0x004 UniqueThread : 0x00b40000 Void # 获取线程TID

有了上述分析结果那么读者可以很容易的获取到当前自身进程的PID以及TID信息,其完整代码片段如下所示,当读者向GetSelfID()传入1则表示读取PID,否则则读取TID信息;

#include <stdio.h>
#include <Windows.h> // 传入1获取PID传入0获取TID
DWORD GetSelfID(DWORD isPid)
{
DWORD ref = 0; if (isPid == 1)
{
__asm
{
mov eax, fs:[0x18] // 获取到PEB基地址
add eax, 0x20 // 加上20得到 _CLIENT_ID
add eax, 0x0 // 加上偏移0得到 UniqueProcess
mov eax, [eax] // 取出内存地址中的值
mov ref, eax
}
}
else
{
__asm
{
mov eax, fs:[0x18] // 获取到PEB基地址
add eax, 0x20 // 加上20得到 _CLIENT_ID
add eax, 0x04 // 加上偏移04得到 UniqueThread
mov eax, [eax] // 取出内存地址中的值
mov ref, eax
}
}
return ref;
} int main(int argc, char* argv[])
{
printf("进程 Pid = %d \n", GetSelfID(1));
printf("线程 Tid = %d \n", GetSelfID(0)); system("pause");
return 0;
}

读者可运行上述代码,并自行打开任务管理器验证是否可以正确获取到,此处执行效果图如下所示;

8.1 TEB与PEB概述的更多相关文章

  1. 从TEB到PEB再到SEH(一)

    什么是TEB? TEB(Thread Environment Block,线程环境块) 线程环境块中存放着进程中所有线程的各种信息 这里我们了解到了TEB即为线程环境块, 进程中每一条线程都对应着的自 ...

  2. 从TEB到PEB再到SEH(二)

    什么是SEH? SEH( Structured Exception Handling , 结构化异常处理 ) 结构化异常处理(SEH)是Windows操作系统提供的强大异常处理功能.而Visual C ...

  3. 旧书重温:0day2【3】 详细解读PEB法 查找kener32地址

    题外话:上一篇文章中的 PEB法查找kerner32地址的方法 对TEB.PEB .PE结构 知识要求很高,确实在写汇编代码时候小编 感觉自己能力,信手啪啪一顿乱撸,结果一运行,非法访问了,没办法翻阅 ...

  4. 【转载】详解CreateProcess调用内核创建进程的过程

    原文:详解CreateProcess调用内核创建进程的过程 昨天同学接到了腾讯的电面,有一题问到了CreateProcess创建进程的具体实现过程,他答得不怎么好吧应该是, 为了以防万一,也为了深入学 ...

  5. 详解CreateProcess调用内核创建进程的过程

    昨天同学接到了腾讯的电面,有一题问到了CreateProcess创建进程的具体实现过程,他答得不怎么好吧应该是, 为了以防万一,也为了深入学习一下,今天我翻阅了好多资料,整理了一下,写篇博客,也算是加 ...

  6. 旧书重温:0day2【2】 实验:三种获取kernel32.dll基址的方法

    0x01 找kernel32基地址的方法一般有三种: 暴力搜索法.异常处理链表搜索法.PEB法. 0x02 基本原理 暴力搜索法是最早的动态查找kernel32基地址的方法.它的原理是几乎所有的win ...

  7. OD: Memory Attach Technology - Exception

    看到第六章了:形形色色的内存攻击技术 异常处理结构体 S.E.H Structure Exception Handler S.E.H 是 Windows 处理异常的重要数据结构.每个 S.E.H 为 ...

  8. Windows 下常见的反调试方法

    稍稍总结一下在Crack或Rervese中比较常见的一些反调试方法,实现起来也比较简单,之后有写的Demo源码参考,没有太大的难度. ①最简单也是最基础的,Windows提供的API接口:IsDebu ...

  9. [5]windows内核情景分析---进程线程

    本篇主要讲述进程的启动过程.线程的调度与切换.进程挂靠 进程的启动过程: BOOL CreateProcess ( LPCTSTR lpApplicationName,                 ...

  10. 通用shellcode

    所有 win_32 程序都会加载 ntdll.dll 和 kernel32.dll 这两个最基础的动态链接库.如果想要 在 win_32 平台下定位 kernel32.dll 中的 API 地址,可以 ...

随机推荐

  1. Linux--修改会话超时时间

    控制用户在一段时间内没有活动时会话的自动注销时间 1.修改ssh配置文件(适用于SSH会话) vim /etc/ssh/sshd_config ClientAliveInterval 1800 #秒 ...

  2. Cpp 值的种类划分

    本博文会介绍移动语义的形式术语和规则.并且会正式的介绍值的类别,如 lvalue.rvalue.prvalue和 xvalue,并讨论了在绑定对象引用时的作用.也会讨论移动语义不会自动传递的细节,以及 ...

  3. 【C++】使用 curl 库配置 HTTP 的 Post/Get 请求响应数据(封装一个简单类)

    2023.7.18 Update: [LibCurl]C++使用libcurl实现HTTP POST和GET 要想使用 LibCURL 库,首先需配置 CURL 库 参考链接:[C++开源库]Wind ...

  4. 4、SpringBoot连接数据库引入druid

    系列导航 springBoot项目打jar包 1.springboot工程新建(单模块) 2.springboot创建多模块工程 3.springboot连接数据库 4.SpringBoot连接数据库 ...

  5. vue权限管理

    https://www.bilibili.com/video/BV1nq4y1i7BU/?spm_id_from=333.788.recommend_more_video.6&vd_sourc ...

  6. Skywalking 的使用

    本文为博主原创,未经允许不得转载: 官网:http://skywalking.apache.org/下载:http://skywalking.apache.org/downloads/Github:h ...

  7. idea相关配置及插件安装

    对idea相关的配置及好用的插件进行总结下. 一.idea 破解码及配置:https://www.jb51.net/softs/672190.html 二.idea插件: 1.findBugs-ide ...

  8. bootstrap : 响应式导航

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...

  9. HTTP 1.1响应码

    HTTP 1.1响应码 响应码和信息 含义 HttpURLConnection 1XX 信息 100 Continue 服务器准备接受请求主体,客户端应当发送请求主体:这允许客户端在请求中发送大量数据 ...

  10. Redis-主从复制-哨兵模式