说 powerful 是最近发现它能运行时加载 machine code,且是运行在 linux 上的 powershell,即使 linux powershell 已经被封印了一部分能力(访问 win native)。本文讨论的 powershell 仅指 6/7,6 以前是另一个东西,不在此讨论。
测试环境
big sur
dotnet --version
7.0.203
pwsh --version
PowerShell 7.3.4
Psl2Csharp
Add-Type
给 powershell 提供了,完整的运行时 .net 的编程语言能力,这是梦开始的地方。
测试 hello world
这种方式比反射调用 static 那种,每次只能调用一个方法方便地多,其中的 .net 代码段和运行在 .net core 上的无异,可替换为任意 todo,方便移植。
Csharp2C
P/Invoke 技术给 .net core 提供了调用 c api 的能力,测试 libc 的 execve
执行 ls -al
这段代码是 chatgpt 生成的,比较简单,没啥可说。
Csharp2Asm
配合 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
Psl2Asm
把前面每步的效果串起来,最终实现 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
原文始发于微信公众号(Moonlight Bug Hunter):Powerful PowerShell For Linux
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论