技术宅的结界

 找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 1486|回复: 4
收起左侧

【C】应用态下不使用任何API获取进程当前路径

[复制链接]

32

主题

91

帖子

3364

积分

用户组: 管理员

UID
1043
精华
14
威望
104 点
宅币
2734 个
贡献
261 次
宅之契约
0 份
在线时间
548 小时
注册时间
2015-8-15
发表于 2018-6-19 23:35:06 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有帐号?立即注册→加入我们

x
在实际应用中,我们经常需要获取当前进程所在的文件路径,而在Visual Basic等各种环境下都有封装好的变量可用于获取路径。但在C中,可能很多人会选择调用一些API来实现,这里本文介绍一种方式,不依赖任何API,通过Windows利用Intel x86及AMD64架构的分段机制的方式来实现查询。毕竟有些时候,总有程序会挂上一些莫名其妙的钩子,我们也正好可以少依赖一些系统函数。
在Intel x86和AMD64架构下有两个特殊的扩充段:fs和gs,其中fs在32位模式的应用态下被指向当前线程的TEB,gs在64位模式的应用态下被指向当前线程的TEB。TEB是Thread Environment Block的缩写,即线程环境块,在这个结构体中存在一个结构体指针,指向PEB,即进程环境块。在PEB中有个成员叫做进程参数,其中包含了进程目录(不含文件名),进程路径(含文件名)以及命令行参数。
上文中提到的所有结构体的具体定义可以参考部分开源的Windows Server 2003的源码中的pebteb.h以及ntpsapi.h文件,为了减少篇幅,这里给出它们的偏移量。
PEB相对于TEB的偏移在32位下是0x30,在64位下是0x60。
进程参数相对于PEB的偏移在32位下是0x10,在64位下是0x20。
进程目录相对于进程参数的偏移在32位下是0x24,在64位下是0x38。
进程路径相对于进程参数的偏移在32位下是0x38,在64位下是0x60。
命令行参数相对于进程参数的偏移在32位下是0x40,在64位下是0x70。
从fs段中取数据,用汇编会很简单,比如我们要取PEB的指针,在32位下是
[mw_shl_code=asm,true]mov eax,dword ptr fs:[0x30][/mw_shl_code]
而在64位下是
[mw_shl_code=asm,true]mov rax,qword ptr gs:[0x60][/mw_shl_code]
不过既然是在写C代码,就应该利用编译器的内置宏来实现这些。
为了简短化执行代码,可以定义这个几个宏用来读TEB:
[mw_shl_code=c,true]#if defined(_WIN64)
#define __readtebbyte        __readgsbyte
#define __readtebword        __readgsword
#define __readtebdword        __readgsdword
#define __readtebqword        __readgsqword
#define __readtebptr        __readgsqword
#else
#define __readtebbyte        __readfsbyte
#define __readtebword        __readfsword
#define __readtebdword        __readfsdword
#define __readtebqword        __readfsqword
#define __readtebptr        __readfsdword
#endif[/mw_shl_code]
其中取指针用__readtebptr就行了。
虽然PEB指针在不同模式下偏移不同,但并不需要使用条件编译分开算。由于一个是0x30,一个是0x60,正好是4和8的12倍,我们将其定义为
[mw_shl_code=c,true]sizeof(void*)*12[/mw_shl_code]
就可以了。如果为了看着舒服也可以专门为其定义一个常量。
同样的,对于进程参数在PEB中的偏移而言,由于一个是0x10,一个0x20,正好是4和8的4倍,怎么定义也不必多说了。
对于进程路径在进程参数的偏移,由于0x38和0x60都分别是4和8的倍数,但因数不等,因此需要使用加法凑出一个相等的因数。
如果心算不行以至于凑不出来的话,就设一个二元一次方程组,使得:
4x+y=0x38;8x+y=0x60
通过加减消元法,可以得出4x=0x28从而得出y=0x10,最终有x=10。
因此,这个偏移量我们可以定义为:
[mw_shl_code=c,true]sizeof(void*)*10+0x10[/mw_shl_code]
同样的道理,进程目录在进程参数的偏移可以定义为:
[mw_shl_code=c,true]sizeof(void*)*5+0x10[/mw_shl_code]
而命令行参数在进程参数的偏移则可以定义为:
[mw_shl_code=c,true]sizeof(void*)*12+0x10[/mw_shl_code]
此外需要注意的一点的是,这三个信息都是以unicode_string这个结构体描述的,其定义如下:
[mw_shl_code=c,true]typedef struct _unicode_string
{
        u16 length;
        u16 maximum_length;
        wchar_t* buffer;
}unicode_string,*unicode_string_p;[/mw_shl_code]
很明显数据通过Unicode编码保存。
在假定已知结构体指针的情况下,在微软CRT中可以通过%wZ来打印字符串,而无需再取buffer通过%ws打印字符串。
说了那么多,贴上具体的代码:
[mw_shl_code=c,true]void no_api_get_path()
{
        ulong_ptr peb_p=__readtebptr(12*sizeof(void*));
        if(peb_p)
        {
                ulong_ptr proc_param=*(ulong_ptr*)(peb_p+sizeof(void*)*4);
                if(proc_param)
                {
                        unicode_string_p dir_path=(unicode_string_p)(proc_param+sizeof(void*)*5+0x10);
                        unicode_string_p img_path=(unicode_string_p)(proc_param+sizeof(void*)*10+0x10);
                        unicode_string_p cmd_line=(unicode_string_p)(proc_param+sizeof(void*)*12+0x10);
                        if(dir_path->buffer)
                                printf("dir: %wZ\n",dir_path);
                        if(img_path->buffer)
                                printf("path: %wZ\n",img_path);
                        if(cmd_line->buffer)
                                printf("cmd: %wZ\n",cmd_line);
                }
        }
}[/mw_shl_code]
效果如图所示:
捕获.PNG

GetSelfPath.7z

636.33 KB, 下载次数: 3

售价: 5 个宅币  [记录]

下载代码不回帖是一种很欠扁的行为

评分

参与人数 1威望 +1 宅币 +10 贡献 +2 收起 理由
0xAA55 + 1 + 10 + 2 屌!

查看全部评分

flowers for Broken spirits - a woman turned into stake will hold the world in the basin of fire.

1048

主题

2341

帖子

6万

积分

用户组: 管理员

一只技术宅

UID
1
精华
218
威望
294 点
宅币
18440 个
贡献
37855 次
宅之契约
0 份
在线时间
1759 小时
注册时间
2014-1-26
发表于 2018-6-19 23:49:22 | 显示全部楼层
这个好,而且避免了对内嵌、外联汇编的依赖。

然而它依赖编译器钦定宏、函数的功能,这些玩意儿不是能够跨编译器的。到那个时候使用汇编等方式可以解决。

总之最终的原理就是跨段读fs、gs段里面的内容,所以不用依赖API。

17

主题

184

帖子

1303

积分

用户组: 上·技术宅

UID
3808
精华
5
威望
31 点
宅币
972 个
贡献
60 次
宅之契约
0 份
在线时间
189 小时
注册时间
2018-5-6
发表于 2018-6-20 08:51:28 | 显示全部楼层
tangptr大神orz
菜鸟一枚,直接指正,不必留情

2

主题

61

帖子

458

积分

用户组: 中·技术宅

UID
2364
精华
0
威望
0 点
宅币
397 个
贡献
0 次
宅之契约
0 份
在线时间
53 小时
注册时间
2017-3-30
发表于 2018-8-2 23:11:45 | 显示全部楼层
本主题由 0xAA55 于 2018-6-19 23:42 加入精华

4

主题

20

帖子

50

积分

用户组: 小·技术宅

UID
4127
精华
0
威望
0 点
宅币
30 个
贡献
0 次
宅之契约
0 份
在线时间
1 小时
注册时间
2018-8-6
发表于 2018-8-6 09:09:09 | 显示全部楼层
哇论坛真的什么都有

本版积分规则

QQ|申请友链||Archiver|手机版|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2019-12-13 02:46 , Processed in 0.096778 second(s), 38 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表