经常看到有人提问在linux中如何获取当前应用程序的绝对路径, 却很少有人能比较好的解答. 现转贴www.linuxforum.net上的一篇文章中的一段, 希望能对受这个问题困扰的人有帮助.
13.12 如何获取当前进程对应之静态映像文件的绝对路径
A: hushui110@水木清华
这是一个x86/Linux Kernel 2.4.7-10系统中利用proc获取绝对路径的例子
--------------------------------------------------------------------------
/*
* gcc -Wall -pipe -g -static -o myprog_2 myprog_2.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define MAXBUFSIZE 1024
int main ( int argc, char * argv[] )
{
char buf[ MAXBUFSIZE ];
int count;
count = readlink( "/proc/self/exe", buf, MAXBUFSIZE );
if ( count < 0 || count >= MAXBUFSIZE )
{
printf( "Failed/n" );
return( EXIT_FAILURE );
}
buf[ count ] = '/0';
printf( "/proc/self/exe -> [%s]/n", buf );
return( EXIT_SUCCESS );
} /* end of main */
--------------------------------------------------------------------------
[scz@ /home/scz/src]> echo $PATH
/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:.
[scz@ /home/scz/src]> ./myprog_2
/proc/self/exe -> [/home/scz/src/myprog_2]
[scz@ /home/scz/src]> ../src/myprog_2
/proc/self/exe -> [/home/scz/src/myprog_2]
[scz@ /home/scz/src]> myprog_2
/proc/self/exe -> [/home/scz/src/myprog_2]
[scz@ /home/scz/src]>
显然这里直接给出了最期待的结果,没有冗余信息。
A: scz <scz@nsfocus.com> & microcat <lgx@nsfocus.com>
2000-03-18
下面在x86/Linux Kernel 2.4.7-10上演示、讨论
--------------------------------------------------------------------------
*
* gcc -Wall -pipe -g -static -o myprog myprog.c
*/
#include <stdio.h>
#include <stdlib.h>
int main ( int argc, char * argv[] )
{
return( EXIT_SUCCESS );
} /* end of main */
--------------------------------------------------------------------------
[scz@ /home/scz/src]> gcc -Wall -pipe -g -static -o myprog myprog.c
[scz@ /home/scz/src]> echo $PATH
/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:.
[scz@ /home/scz/src]> gdb ./myprog
(gdb) b main
(gdb) r
(gdb) x/17s 0xbfffff00
0xbfffff00: "SHLVL=1"
0xbfffff08: "_=/bin/bash"
0xbfffff14: "SHELL=/bin/bash"
0xbfffff24: "HOSTTYPE=i386"
0xbfffff32: "OSTYPE=linux-gnu"
0xbfffff43: "HISTSIZE=1000"
0xbfffff51: "TERM=vt100"
0xbfffff5c: "HOME=/home/scz"
0xbfffff6b: "SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass"
0xbfffff9e: "PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:."
0xbfffffd2: "LESSCHARSET=latin1"
0xbfffffe5: "/home/scz/src/./myprog" <-- 注意这个输出
0xbffffffc: ""
0xbffffffd: ""
0xbffffffe: ""
0xbfffffff: ""
0xc0000000: <Address 0xc0000000 out of bounds>
[scz@ /home/scz/src]> gdb myprog
(gdb) b main
(gdb) r
(gdb) x/17s 0xbfffff00
0xbfffff00: "z"
0xbfffff02: "SHLVL=1"
0xbfffff0a: "_=/bin/bash"
0xbfffff16: "SHELL=/bin/bash"
0xbfffff26: "HOSTTYPE=i386"
0xbfffff34: "OSTYPE=linux-gnu"
0xbfffff45: "HISTSIZE=1000"
0xbfffff53: "TERM=vt100"
0xbfffff5e: "HOME=/home/scz"
0xbfffff6d: "SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass"
0xbfffffa0: "PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:."
0xbfffffd4: "LESSCHARSET=latin1"
0xbfffffe7: "/home/scz/src/myprog" <-- 注意这个输出
0xbffffffc: ""
0xbffffffd: ""
0xbffffffe: ""
0xbfffffff: ""
[scz@ /home/scz/src]> gdb ../src/myprog
(gdb) b main
(gdb) r
(gdb) x/17s 0xbfffff00
0xbfffff00: "=1"
0xbfffff03: "_=/bin/bash"
0xbfffff0f: "SHELL=/bin/bash"
0xbfffff1f: "HOSTTYPE=i386"
0xbfffff2d: "OSTYPE=linux-gnu"
0xbfffff3e: "HISTSIZE=1000"
0xbfffff4c: "TERM=vt100"
0xbfffff57: "HOME=/home/scz"
0xbfffff66: "SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass"
0xbfffff99: "PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:."
0xbfffffcd: "LESSCHARSET=latin1"
0xbfffffe0: "/home/scz/src/../src/myprog" <-- 注意这个输出
0xbffffffc: ""
0xbffffffd: ""
0xbffffffe: ""
0xbfffffff: ""
0xc0000000: <Address 0xc0000000 out of bounds>
[scz@ /home/scz/src]>
这是ELF文件在Linux系统中加载进内存之后的布局简图
--------------------------------------------------------------------------
0x08048000 code .text,代码,只读
data .data,包含已经初始化的数据,只读
bss .bss,未初始化数据,初始化成0,读/写
... 堆区,动态分配获取的内存从.bss往内存高端增长
... (heap),读/写
...
stack 栈区,起始地址大于0xBFFF0000
arguments main()的形参
environment 环境变量区域
program name execve()第一形参,不是argv[0]
0xBFFFFFFC null(dword) 最后四个字节固定为零
0xC0000000
--------------------------------------------------------------------------
通常动态链接库被映射到0x40000000往高端的地址。对于Linux,如果打了不可执行
堆栈内核补丁,动态链接库被映射到0x40000000往低端的地址。tt说就是以前的映射
地址减去0x40000000。打了补丁后使得通过字符串拷贝(strcpy)传递shellcode相对
复杂化,需要更多技巧。
program name处不一定是绝对路径,实际对应了execve()第一形参。一般从shell上
启动进程,shell根据PATH环境变量自动搜索匹配出一个路径,未必是绝对路径。假
设PATH环境变量中有当前目录(.),所执行的程序也只在当前目录下有,直接指定程
序名(myprog)执行时,shell会向execve()第一形参传递"./myprog"。注意,execve
第一形参未必是绝对路径。用gdb加载后再执行,情况有所不同。如果gdb命令行上指
定的程序名非绝对路径,gdb在调用execve()之前会调用getcwd()拼接在程序名之前,
此时不依赖PATH环境变量。所以用gdb调试溢出程序时应该在命令行上指定绝对路径,
避免不必要的偏移调整。
现在来看这样一个演示程序
--------------------------------------------------------------------------
/*
* gcc -Wall -pipe -g -static -o myprog_1 myprog_1.c
*/
#include <stdio.h>
#include <stdlib.h>
extern char **environ;
int main ( int argc, char * argv[] )
{
char *path = ( char * )( 0xc0000000 - 5 );
while ( *--path );
++path;
printf( "path --> %08x [%s]/n", ( unsigned int )path, path );
printf( "argv --> %08x/n", ( unsigned int )argv );
printf( "argv[0] --> %08x [%s]/n", ( unsigned int )argv[0],
argv[0] );
printf( "environ --> %08x/n", ( unsigned int )environ );
printf( "environ[0] --> %08x [%s]/n", ( unsigned int )environ[0],
environ[0] );
return( EXIT_SUCCESS );
} /* end of main */
--------------------------------------------------------------------------
获取本程序绝对路径
最新推荐文章于 2024-09-20 20:44:35 发布