首先,当有新连接进来的时候,fork一个子进程,然后进入上面代码中的那个分支,
这时候我们发送一个命令
然后有几个比较重要的操作:
首先是把输入的16356赋值给
然后把
再做完这些的操作后,进入了
然后进入
首先,我们发送16352个a作为padding,然后执行了下面这流程:
storeextend return 0 -> storeget -> store_release
先申请了一个0x4010的heap2,然后释放了长度为0x2010的heap1
然后发送
跳到了EOL,最重要的是最后几行代码:
把一些变量重新进行了初始化,因为之前因为padding执行了
渗透爬虫软件 资源采集 劫持域名 提取抓料子 六合·色站·彩票·博彩·金融 接渗透拿站,各大网站数据-拖库-提权联系 域名劫持 DNS 入侵网站 联系:@hacker_HouZiM
smtp_setup_msg函数是用来接收命令的函数,我们先发一堆无效的命令过去(padding),控制yield_length的值小于0x100,目的上一篇文章说过了,因为命令无效,流程再一次进入了smtp_setup_msg这时候我们发送一个命令
BDAT 16356然后有几个比较重要的操作:
5085 if (sscanf(CS smtp_cmd_data, "%u %n", &chunking_datasize, &n) < 1)
5093 chunking_data_left = chunking_datasize;
5100 lwr_receive_getc = receive_getc;
5101 lwr_receive_getbuf = receive_getbuf;
5102 lwr_receive_ungetc = receive_ungetc;
5104 receive_getc = bdat_getc;
5105 receive_ungetc = bdat_ungetc;
首先是把输入的16356赋值给
chunking_data_left然后把
receive_getc换成bdat_getc函数再做完这些的操作后,进入了
receive_msg函数,按照上篇文章的流程差不多,显示申请了一个0x100的heap1然后进入
receive_getc=bdat_getc读取数据:534 int
535 bdat_getc(unsigned lim)
536 {
......
546 if (chunking_data_left > 0)
547 return lwr_receive_getc(chunking_data_left--);
lwr_receive_getc=smtp_getc通过该函数获取16356个字符串首先,我们发送16352个a作为padding,然后执行了下面这流程:
storeextend return 0 -> storeget -> store_release
先申请了一个0x4010的heap2,然后释放了长度为0x2010的heap1
然后发送
:\r\n,进入下面的代码分支:1902 if (ch == '\r')
1903 {
1904 ch = (receive_getc)(GETC_BUFFER_UNLIMITED);
1905 if (ch == '\n')
1906 {
1907 if (first_line_ended_crlf == TRUE_UNSET) first_line_ended_crlf = TRUE;
1908 goto EOL;
1909 }
跳到了EOL,最重要的是最后几行代码:
2215 header_size = 256;
2216 next = store_get(sizeof(header_line));
2217 next->text = store_get(header_size);
2218 ptr = 0;
2219 had_zero = 0;
2220 prevlines_length = 0;
2221 } /* Continue, starting to read the next header */
把一些变量重新进行了初始化,因为之前因为padding执行了
store_get(0x4000),所以这个时候yield_length=0 这个时候再次调用store_get将会申请一个0x2000大小堆,从unsortbin中发现heap1大小正好合适,所以这个时候得到的就是heap1,在heap1的顶上有一个之前next->text使用,大小0x4010,未释放的堆。渗透爬虫软件 资源采集 劫持域名 提取抓料子 六合·色站·彩票·博彩·金融 接渗透拿站,各大网站数据-拖库-提权联系 域名劫持 DNS 入侵网站 联系:@hacker_HouZiM
在
在
渗透爬虫软件 资源采集 劫持域名 提取抓料子 六合·色站·彩票·博彩·金融 接渗透拿站,各大网站数据-拖库-提权联系 域名劫持 DNS 入侵网站 联系:@hacker_HouZiM
include/auth.php, L:81-172中判断用户是否登录,未登录用户加载auth_login.php进行登录,已登录用户显示后台界面if (empty($_SESSION['sess_user_id'])) {
include($config['base_path'] . '/auth_login.php');
exit;
} elseif (!empty($_SESSION['sess_user_id'])) {
...
include_once('./include/global_session.php');
...
}在
auth_login.php, L:576,683 读取当前页面路径拼接进入action<form name='login' method='post' action='<?php print get_current_page();?>'>
......
<?php include_once('./include/global_session.php');?>
lib/function.php, L:2889-2913 PHP_SELF返回当前执行脚本的文件名,但在pathinfo模式下PHP_SELF会返回从文件名到query_string之前的部分。由于pathinfo中的单引号不会被转义,可以在form中构造反射型xss,但这样只会影响未登录用户。function get_current_page($basename = true) {
if (isset($_SERVER['PHP_SELF']) && $_SERVER['PHP_SELF'] != '') {
if ($basename) {
return basename($_SERVER['PHP_SELF']);
} else {
return $_SERVER['PHP_SELF'];
}
} elseif(){
......
}
return false;
}include/global_session.php, L:91 获取REQUEST_URL过滤html标签过来非url字符后作为js参数拼接进入字符串。同理配合pathinfo模式引入单引号构造反射型xss,同时影响登录用户和未登录用户。var requestURI='<?php print filter_var(strip_tags($_SERVER['REQUEST_URI']), FILTER_SANITIZE_URL);?>';渗透爬虫软件 资源采集 劫持域名 提取抓料子 六合·色站·彩票·博彩·金融 接渗透拿站,各大网站数据-拖库-提权联系 域名劫持 DNS 入侵网站 联系:@hacker_HouZiM
在这些假设下,
_i:子生成器,同时也是一个迭代器
_y:子生成器生产的值
_r:yield from 表达式最终的值
_s:调用方通过
_e:异常对象
这段代码的大部分含义已经在注释中说明了,可以结合注释来理解这段代码的含义。
如果你已经理解了,那么我们继续。现实情况下,
子生成器可能只是一个迭代器,并不是一个作为协程的生成器,所以它不支持
如果子生成器支持
调用方让子生成器自己抛出异常,没有原因,就是任性;
当调用方使用
这些问题都是
子生成器生产的值,都是直接传给调用方的;调用方通过
子生成器退出的时候,最后的
如果调用的时候出现
传入委托生成器的异常里,除了
如果在委托生成器上调用
渗透爬虫软件 资源采集 劫持域名 提取抓料子 六合·色站·彩票·博彩·金融 接渗透拿站,各大网站数据-拖库-提权联系 域名劫持 DNS 入侵网站 联系:@hacker_HouZiM
RESULT = yield from EXPR可以简化成下面这样,在读这段代码之前,我们先说明一下这些下划线开头的变量的作用:_i:子生成器,同时也是一个迭代器
_y:子生成器生产的值
_r:yield from 表达式最终的值
_s:调用方通过
send()发送的值_e:异常对象
这段代码的大部分含义已经在注释中说明了,可以结合注释来理解这段代码的含义。
如果你已经理解了,那么我们继续。现实情况下,
yield from要做的事情会复杂一些,毕竟我们做出了一系列的假设。将假设去掉没有什么难度,但是有几个问题非常难受:子生成器可能只是一个迭代器,并不是一个作为协程的生成器,所以它不支持
.throw()和.close()方法;如果子生成器支持
.throw()和.close()方法,但是在子生成器内部,这两个方法都会抛出异常;调用方让子生成器自己抛出异常,没有原因,就是任性;
当调用方使用
next()或者.send(None)时,都要在子生成器上调用next()函数,当调用方使用.send()发送非 None 值时,才调用子生成器的.send()方法;这些问题都是
yield from结构需要考虑的事情,下面我们来看一下完成的简化之前的代码,相关的注解也写到了注释中:子生成器生产的值,都是直接传给调用方的;调用方通过
.send()发送的值都是直接传递给子生成器的;如果发送的是 None,会调用子生成器的__next__()方法,如果不是 None,会调用子生成器的.send()方法;子生成器退出的时候,最后的
return EXPR,会触发一个StopIteration(EXPR)异常;yield from表达式的值,是子生成器终止时,传递给StopIteration异常的第一个参数;如果调用的时候出现
StopIteration异常,委托生成器会恢复运行,同时其他的异常会向上 "冒泡";传入委托生成器的异常里,除了
GeneratorExit之外,其他的所有异常全部传递给子生成器的.throw()方法;如果调用.throw()的时候出现了StopIteration异常,那么就恢复委托生成器的运行,其他的异常全部向上 "冒泡";如果在委托生成器上调用
.close()或传入GeneratorExit异常,会调用子生成器的.close()方法,没有的话就不调用。如果在调用.close()的时候抛出了异常,那么就向上 "冒泡",否则的话委托生成器会抛出GeneratorExit异常。渗透爬虫软件 资源采集 劫持域名 提取抓料子 六合·色站·彩票·博彩·金融 接渗透拿站,各大网站数据-拖库-提权联系 域名劫持 DNS 入侵网站 联系:@hacker_HouZiM
我们从一个简单的爬虫开始,这个爬虫很简单,访问指定的 URL,并且获取内容并计算长度,这里我们给定 5 个 URL。第一版的代码十分简单,顺序获取每个 URL 的内容,当第一个请求完成、计算完长度后,再开始第二个请求。
我们多运行几次看看结果。
大约需要花费 14-16 秒不等,这段代码并没有什么好看的,我们把关注点放在后面的代码上。现在我们使用多线程来改写这端代码。
再来看一下结果,很明显,我们的耗时已经降低到 10s 左右了:
从这两段代码中,已经可以看出并发对于处理任务的好处了,但是使用原生的
执行一下,会发现耗时与上一个版本一样,稳定在 10s 左右。
可以看到我们调用了
渗透爬虫软件 资源采集 劫持域名 提取抓料子 六合·色站·彩票·博彩·金融 接渗透拿站,各大网站数据-拖库-提权联系 域名劫持 DNS 入侵网站 联系:@hacker_HouZiM
我们多运行几次看看结果。
大约需要花费 14-16 秒不等,这段代码并没有什么好看的,我们把关注点放在后面的代码上。现在我们使用多线程来改写这端代码。
再来看一下结果,很明显,我们的耗时已经降低到 10s 左右了:
从这两段代码中,已经可以看出并发对于处理任务的好处了,但是使用原生的
threading模块还是略显麻烦,Python 已经给我们内置了一个处理并发任务的库concurrent,我们借用这个库修改一下我们的代码,之所以修改成这个库的原因还有一个,那就是引出我们后面会谈到的Future。执行一下,会发现耗时与上一个版本一样,稳定在 10s 左右。
可以看到我们调用了
concurrent库中的futures,那么到底什么是futures?简单的讲,这个对象代表一种异步的操作,可以表示为一个需要延时进行的操作,当然这个操作的状态可能已经完成,也有可能尚未完成,如果你写 JS 的话,可以理解为是类似Promise的对象。在 Python 中,标准库中其实有两个Future类,一个是concurrent.futures.Future,另外一个是asyncio.Future,这两个类很类似,不完全相同,这些实现差异以及 API 的差异我们先按下暂且不谈,有兴趣的同学可以参考下相关的文档。Future是我们后面讨论的asyncio异步编程的基础,因此这里多说两句。Future代表的是一个未来的某一个时刻一定会执行的操作(可能已经执行完成了,但是无论如何他一定有一个确切的运行时间),一般情况下用户无需手动从零开始创建一个 Future,而是应当借助框架中的 API 生成。比如调用concurrent.futures.Executor.submit()时,框架会为 "异步操作" 进行一个排期,来决定何时运行这个操作,这时候就会生成一个Future对象。渗透爬虫软件 资源采集 劫持域名 提取抓料子 六合·色站·彩票·博彩·金融 接渗透拿站,各大网站数据-拖库-提权联系 域名劫持 DNS 入侵网站 联系:@hacker_HouZiM
拿到
从头部加密信息来看,是用的 PHPJiaMi,看到代码里面有
直接解该文件没成功,说明存在调用才会解密的情况,从
把原来的
然后把
把
渗透爬虫软件 资源采集 劫持域名 提取抓料子 六合·色站·彩票·博彩·金融 接渗透拿站,各大网站数据-拖库-提权联系 域名劫持 DNS 入侵网站 联系:@hacker_HouZiM
UploadFile.class.php,部分代码如下:从头部加密信息来看,是用的 PHPJiaMi,看到代码里面有
eval,那这种方式解密成功率就很大了。直接解该文件没成功,说明存在调用才会解密的情况,从
index.php 里发现了调用的代码。 if($_FILES) {
include 'UploadFile.class.php';
$dist = 'upload';
$upload = new UploadFile($dist, 'upfile');
$data = $upload->upload();
}
?>把原来的
index.php 拿过来,我们需要在上面2中的代码前构造表单里的变量,让它能成功执行,所以我们最终的 index.php 是这个样子<?php
$_FILES["upfile"] = array(
"name" => "1303.jpg",
"type" => "image/jpeg",
"tmp_name" => "/tmp/php/phpSDsuf7",
"error" => 0,
"size" => 1024
);
// 上面的代码是加的
if($_FILES) {
include 'UploadFile.class.php';
$dist = 'upload';
$upload = new UploadFile($dist, 'upfile');
$data = $upload->upload();
}
?><!DOCTYPE html>
<html>
....后面省略
然后把
index.php 和 UploadFile.class.php 打个 zip 包, 注意 index 所在的目录不要打包进去$ zip -r mytest.zip index.php UploadFile.class.php
把
mytest.zip 上传后,如果出现解密失败,点后面的重试,就能看到结果了。渗透爬虫软件 资源采集 劫持域名 提取抓料子 六合·色站·彩票·博彩·金融 接渗透拿站,各大网站数据-拖库-提权联系 域名劫持 DNS 入侵网站 联系:@hacker_HouZiM
程序通过判断文件名来对请求进行不同的处理。跟进 handlePhpCgi 后可以看到对请求参数、请求头进行解析后将执行权交给 php,解析过程如下:
对参数进行解析后,将其储存以键值对的形式(_TYPE_KEY=VALUE,TYPE 为 GET、POST、SERVER),并以 \n 分隔储存到一字符串中,调试如下:
然后进行认证检查,将检查的结果赋值给 AUTHORIZED_GROUP 并保存到字符串中作为全局变量传递给 php:
在整个解析流程中并没有对参数中的 \n 进行过滤,所以如果通过注入 \n 进而注入 AUTHORIZED_GROUP 就可以绕过认证检查,未经授权执行 php 脚本。
在认证通过后程序获取 $_POST["SERVICES"] 参数,将其拼接到字符串中进行包含。/htdocs/webinc/getcfg/ 目录(也可以通过 ../ 跳转目录)下为路由的配置文件,比如 DEVICE.ACCOUNT.xml.php 中保存着路由的管理密码:
渗透爬虫软件 资源采集 劫持域名 提取抓料子 六合·色站·彩票·博彩·金融 接渗透拿站,各大网站数据-拖库-提权联系 域名劫持 DNS 入侵网站 联系:@hacker_HouZiM
对参数进行解析后,将其储存以键值对的形式(_TYPE_KEY=VALUE,TYPE 为 GET、POST、SERVER),并以 \n 分隔储存到一字符串中,调试如下:
然后进行认证检查,将检查的结果赋值给 AUTHORIZED_GROUP 并保存到字符串中作为全局变量传递给 php:
在整个解析流程中并没有对参数中的 \n 进行过滤,所以如果通过注入 \n 进而注入 AUTHORIZED_GROUP 就可以绕过认证检查,未经授权执行 php 脚本。
在认证通过后程序获取 $_POST["SERVICES"] 参数,将其拼接到字符串中进行包含。/htdocs/webinc/getcfg/ 目录(也可以通过 ../ 跳转目录)下为路由的配置文件,比如 DEVICE.ACCOUNT.xml.php 中保存着路由的管理密码:
渗透爬虫软件 资源采集 劫持域名 提取抓料子 六合·色站·彩票·博彩·金融 接渗透拿站,各大网站数据-拖库-提权联系 域名劫持 DNS 入侵网站 联系:@hacker_HouZiM