# 代码不显示。只需将75 c7 更改为75 00 即可。
[root@localhost test]# ./a.out 5446 4006a3 # 基址(0x400000) + 偏移量(0x6a2+1)
我们用psss来看看情况。
值:5446 地址:0x7ffd4943cf18 pid:5446
值:5446 地址:0x7ffd4943cf18 pid:5446
值:5446 地址:0x7ffd4943cf18 pid:5446
让我们打破循环吧!
成功逃离无限循环!
接下来,尝试简单的进程注入来调用僵尸函数。
请参阅原始程序代码。
//pokestack.c
#include stdio.h
#包括stdlib.h
void Say\\_hi()
{
printf(\’皮鞋\\n\’);
结束(0);
}
int main(int argc, char \\*\\*argv)
{
int tf=atoi(argv[1]);
长a=0x1122334455667788;
而(tf){
printf(\’value:%lx 地址:%p pid:%d\\n\’, a, a, getpid());
sleep(120); //120秒内完成手动操作。您还可以使用getchar。
}
printf(\’请中断循环!\\n\’);
}
请注意,我们没有在任何地方调用Say_hi 函数。接下来,修改mem文件,以便该程序可以调用Say_hi。
让我们从运行开始:
[root@localhost 测试]# ./pokestack 1
值:1122334455667788 地址:0x7fff75a4ba80 pid:5553
与往常一样,这次的目标是在堆栈中找到推送的唤醒地址并更改它。
如果你不想每次都检查堆栈位置,你可以像这样关闭ASLR 保护:
sysctl -w kernel.randomize_va_space=0
然而,这里并没有使用这个技巧,以使事情变得更加真实。在现实环境中,ASLR 很少被关闭。
毕竟堆栈位置是随机的,而且每次都不同,所以需要检查一下。
[root@localhost test]# cat /proc/5553/smaps |grep -E \\\\[stack\\\\]
7fff75a2c000-7fff75a4d000 rw-p 00000000 00:00 0 [堆栈]
[root@localhost test]# dd if=/proc/5553/mem of=./pokestack.dd Skip=140735166988288 bs=1 count=557056
记录135168+0次读取
记录135168+0次写入
135168 字节(135 KB) 副本,0.165683 秒,816 KB/秒
[root@localhost 测试]# hexdump ./pokestack.dd ./pokestack.hex
我开始在pokestack.hex中寻找sleep的返回地址,发现了这一行:
001fa60 bb70 75a4 7fff 0000 06ff 0040 0000 0000
这就是4006ff 的全部内容。
如何找到它们超出了本文的范围,只需按照以下模式进行匹配即可:
返回main函数应该是400000左右.
我们将其更改为say_hi 的地址:
#0x7FFF75A4BA68是堆栈基地址与0x001fa60+0x8之和。
#0x000000000040067d 是say\\_hi 的地址。
# 将位置0x7FFF75A4BA68的值更改为0x000000000040067d
[root@localhost 测试]# ./a.out 55530x7FFF75A4BA680x000000000040067d
等待它重新进入睡眠状态,然后检查效果。
值:1122334455667788 地址:0x7fff75a4ba80 pid:5553
皮鞋
[root@localhost 测试]#
效果不错。
现在让我们将另一个代码注入到已经运行的进程中。
//pokestack.c
#include stdio.h
#包括stdlib.h
int main(int argc, char \\*\\*argv)
{
\\_\\_asm(\’mov $123, %rdi\\n\’); //该语句导出退出系统调用参数123 的命令代码。
另一方面(1) {
printf(\’pid:%d\\n\’, getpid());
睡眠(120);
}
}
导出堆栈信息。
[root@localhost test]# cat /proc/6033/smaps |grep -E -A2 \\\\[stack\\\\]
7ffe66868000-7ffe66889000 rw-p 00000000 00:00 0 [堆栈]
大小: 136KB
RSS: 16kB
请注意,堆栈没有执行权限,因此必须将其插入二进制文件的文本部分。
如果堆栈是可执行的,您所需要做的就是用注入代码覆盖堆栈的开头,堆栈将处于运行状态(堆栈从上到下增长,因此通常不会增长那么远) )。这并不难。只需使用以下命令编译它:
[root@localhost test]# gcc -O0 -z execstack pokestack.c -o pokestack
然而,为了让事情更现实,没有使用这个技巧,因为在真实环境中使堆栈可执行的方法很少。
现在我们来看一下二进制文本段信息。
[root@localhost test]# cat /proc/6033/smaps |grep -A2 r-xp.\\*pokestack
00400000-00401000 r-xp 00000000 fd:00 75346995 /usr/test/pokestack
大小: 4kB
Rss: 4kB
实现注入的代码如下:
#include sys/types.h
#include sys/stat.h
#包括fcntl.h
#include stdio.h
#包括stdlib.h
int main(int argc, char \\*\\*argv)
{
角色名称[32];
int fd;
PID;
无符号长caddr、raddr;
无符号长ret_addr;
//代码只是一个exit(123) 系统调用
字符代码[14]={0x48,0xc7,0xc7,0x7b,0x00,0x00,0x00,0xb8,0x3c,0x00,0x00,0x00,0x0f,0x05};
pid=atoi(argv[1]);
caddr=strtoul(argv[2], NULL, 16);
raddr=strtoul(argv[3], NULL, 16);
sprintf(名称, \’/proc/%d/mem\’, pid);
fd=open(名称, O_RDWR);
lseek(fd, caddr, SEEK\\_SET);
写(fd,代码,sizeof(代码));
lseek(fd, raddr, SEEK\\_SET);
写(fd,caddr,sizeof(caddr));
}
代码不再解释,直接看效果。
#0x7FFE66887998 仍然是dd 方法导出的堆栈中找到的返回地址地址。
[root@localhost 测试]# ./a.out 60330x004000000x7FFE66887998
查看进程号6033 的末尾。
[root@localhost 测试]# ./pokestack
pid:6033
[root@localhost 测试]# echo $?
一二三
最终以123分顺利结束。
下次为什么不尝试打印呢?大量印刷。
您需要插入对printf 的调用,但该调用通常使用相对偏移量进行调用,因此使用以下方法:
推送printf@GLIBC
让
但是printf 在哪里呢?让我们先快速解释一下。直接调用write 系统调用。
我们先看一下原来的代码。
#include stdio.h
#包括stdlib.h
int main(int argc, char \\*\\*argv)
{
另一方面(1) {
printf(\’pid:%d\\n\’, getpid());
getchar();
}
}
开始运行:
[root@localhost 测试]# ./pokestack
pid:14917
pid:14917
. # 按住任意键仍然执行getchar。这是一个无限循环。
一步步获取信息。
[root@localhost test]# cat /proc/14917/smaps |grep -E \\\\[stack\\\\]
7ffc08ac1000-7ffc08ae2000 rw-p 00000000 00:00 0 [堆栈]
[root@localhost test]# dd if=/proc/14917/mem of=./pokestack.dd Skip=140720453980160 bs=1 count=557056
[root@localhost 测试]# hexdump ./pokestack.dd ./pokestack.hex
.
我在pokestack.hex 中找到了以下行:
001f4a0 0000 0000 0000 0000 05dc 0040 0000 0000
拼接偏移:
0x7ffc08ac1000 +0x001f4a0 +0x08=0x7FFDF4F9E818
编写注入代码并实现注入的代码如下:
#include sys/types.h
#include sys/stat.h
#包括fcntl.h
#include stdio.h
#包括stdlib.h
int main(int argc, char \\*\\*argv)
{
角色名称[32];
int fd;
PID;
无符号长caddr、raddr;
无符号长ret_addr;
字符代码[58]={/\\*0x00\\*/0x61,0x61,0x61,0x0a,
/*0x04\\*/0x00,0x00,0x00,0x00,
/*0x08\\*/0x00,0x00,0x00,0x00,
/*0x0c*/0x00,0x00,0x00,0x00,
/*0x10\\*/0x48,0xc7,0xc7,0x01,0x00,0x00,0x00, //移动1, rdi
0x48,0xc7,0xc6,0x00,0x00,0x40,0x00, //移动400000, rsi
0x48,0xc7,0xc2,0x04,0x00,0x00,0x00, //移动4, rdx
0xb8,0x01,0x00,0x00,0x00, //移动1, eax
0x0f,0x05,//写入系统调用
0x48,0xc7,0xc7,0x7b,0x00,0x00,0x00, //移动123, rdi
0xb8,0x3c,0x00,0x00,0x00, //移动60, eax
0x0f,0x05}; //完成系统调用。
pid=atoi(argv[1]);
caddr=strtoul(argv[2], NULL, 16);
raddr=strtoul(argv[3], NULL, 16);
sprintf(名称, \’/proc/%d/mem\’, pid);
fd=open(名称, O_RDWR);
lseek(fd, caddr, SEEK\\_SET);
写(fd,代码[0],sizeof(代码));
caddr +=0x10; //从mov 1,rdi开始执行。
lseek(fd, raddr, SEEK\\_SET);
写(fd,caddr,sizeof(caddr));
}
实现注入:
[root@localhost 测试]# ./a.out 149170x004000000x7FFC08AE04A8
检查效果:
[root@localhost 测试]# ./pokestack
pid:14917
pid:14917
啊
[root@localhost 测试]# echo $?
一二三
[root@localhost 测试]#
是的,我摆脱了无限循环,最终得到了123。
是不是比ptrace更好玩?
……
我们希望直接调用GLIBC库函数,而不是直接调用系统调用。其实,这并不难。
首先看一下下面的代码。
#include stdio.h
char abc1[]=\’aaaa\\n\’;
int main()
{
printf(\’\\n\\n\’); //加载程序时解析printf 函数
\\_\\_asm(\’mov $0x000000000060102c, %rdi\’); //abc1 的地址作为rdi 寄存器的参数给出
\\_\\_asm(\’push $0x40053d\’) //主函数之后的位置\\_asm(\’ret\’)
\\_\\_asm(\’push $0x0000000000400400\’); //printf 位置
\\_\\_asm(\’ret\’);
}
所有数字都可以从objdump 手动找到。
运行并检查是否输出aaaa。
使用该方法来实现注入。这仍然是一个原始程序。
#include stdio.h
#包括stdlib.h
int main(int argc, char \\*\\*argv)
{
另一方面(1) {
printf(\’pid:%d\\n\’, getpid());
getchar();
}
}
开始运行:
[root@localhost 测试]# ./pokestack
![](https://img-blog.csdnimg.cn/img_convert/9a8cb5f8c0ec69e6499adead0da6e95b.png)
适合Linux 初学者和专家的最全面的Linux 教程。
=====================
1. **Linux从初学者到专家(第二版)**
2. **移植Linux系统**
3. **Linux驱动开发介绍与实践**
4. **LINUX系统移植第二版**
5. **详细讲解Linux开源网络全栈,从DPDK到OpenFlow**
!【华为18级工程师苦心编写3000页Linux学习笔记本教程】(https://img-blog.csdnimg.cn/img_convert/59742364bb1338737fe2d315a9e2ec54.png)
第一版《Linux从入门到精通》 466 页
===================
简单的介绍
====
这是经典Linux畅销书**《Linux从入门到精通》**的第二版,受到了众多读者的好评。本书第一版自出版以来已多次印刷,并荣获51CTO读书频道“最受读者喜爱的原创IT技术图书奖”。书号?本书采用最新的Ubuntu 12.04版本,循序渐进地向读者介绍Linux基本应用、系统管理、网络应用、娱乐办公、程序开发、服务器配置、系统安全等。本书附带一张CD,其中包含支持本书的多媒体教育视频。另外,本书还为读者提供了大量的Linux学习资料和Ubuntu安装镜像文件供读者免费下载。
!【华为18年级工程师苦心编写3000页Linux学习笔记本教程】(https://img-blog.csdnimg.cn/img_convert/9d4aefb6a92edea27b825e59aa1f2c54.png)
**本书适合初、中级Linux用户、开源软件爱好者、大学生。它还适合准备进行Linux 平台开发的各类人员。 **
需要《Linux入门到精通》、《linux系统移植》、《Linux驱动开发入门实战》、《Linux开源网络全栈》电子书和教程的工程师朋友请转发评论。
# 以上修改Linux进程地址空间实现代码注入的相关内容摘自网络,仅供参考。相关信息请参见官方公告。
原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/92133.html