说 powerful 是最近发现它能运行时加载 machine code,且是运行在 linux 上的 powershell,即使 linux powershell 已经被封印了一部分能力(访问 win native)。本文讨论的 powershell 仅指 6/7,6 以前是另一个东西,不在此讨论。
`ubuntu20/macos big sur`` ``dotnet --version``7.0.203`` ``pwsh --version``PowerShell 7.3.4`
Add-Type
给 powershell 提供了,完整的运行时 .net 的编程语言能力,这是梦开始的地方。
测试 hello world
这种方式比反射调用 static 那种,每次只能调用一个方法方便地多,其中的 .net 代码段和运行在 .net core 上的无异,可替换为任意 todo,方便移植。
P/Invoke 技术给 .net core 提供了调用 c api 的能力,测试 libc 的 execve
执行 ls -al
这段代码是 chatgpt 生成的,比较简单,没啥可说。
配合 linux 加载内存的方式,不调用 exec
族函数,加载 machine code,测试最简单的系统调用 ls -al
最终代码是 chatgpt 生成的,我给了它一个 c 版本的作为输入,所以它实际上是做了一个 translation。还是帮了不少忙,不然我得一个个对着两边的文档去翻译。小瑕疵是不够 readable,懒得 prompt 了。
我最初自己写时尝试直接用 mprotect
改托管变量 shellcode
的 protect settings 没成功,推测可能的原因是
centos 不允许同时设置 PROT_READ | PROT_WRITE | PROT_EXEC
linux 不允许像 windows 那样直接用 api 去改另一个进程的 memory map
shellcode 是手敲之后,用 https://defuse.ca/online-x86-assembler.htm 转的,顺便复习了汇编,快10年没写这玩意儿了,边敲边感慨丹尼斯·里奇的伟大
`.section .text``.global _start``_start:`` ` `xorq %rdx,%rdx # param3`` push %rdx`` ` `movq $0x616c2d,%r8` `push %r8` `movq $0x736c2f6e69622f,%r8` `push %r8` ` mov %rsp, %rdi # param1`` ` `push %rdx` `lea 8(%rdi), %rcx` `push %rcx` `push %rdi`` ` `mov %rsp, %rsi # param2`` ` `push $0x3b` `pop %rax` `syscall`` ` `xorq %rdi, %rdi` `push $0x3c` `pop %rax` `syscall`
把前面每步的效果串起来,最终实现 powershell invoke asm
powershell 是跨平台的,osx 也可以,略微有些区别,直接把官网代码改吧改吧就能跑
https://man7.org/linux/man-pages/man2/mmap.2.html
https://man7.org/linux/man-pages/man2/mprotect.2.html
https://man7.org/linux/man-pages/man3/memcpy.3.html
https://learn.microsoft.com/en-us/dotnet/standard/native-interop/pinvoke