菜狗子的学习记录

07
Dec

利用Mock进行模拟数据

Mock.js 是一款模拟数据生成器,旨在帮助前端攻城师独立于后端进行开发,帮助编写单元测试。提供了以下模拟功能:

根据数据模板生成模拟数据
模拟 Ajax 请求,生成并返回模拟数据
基于 HTML 模板生成模拟数据

语法规范

Mock.js 的语法规范包括两部分:

数据模板定义(Data Temaplte Definition,DTD)
数据占位符定义(Data Placeholder Definition,DPD)
mockRespCode

数据模板定义DTD

数据模板中的每个属性由 3 部分构成: 属性名、生成规则、属性值

// 属性名   name
// 生成规则 rule
// 属性值   value
'name|rule': value
'name|min-max': value
'name|count': value
'name|min-max.dmin-dmax': value
'name|min-max.dcount': value
'name|count.dmin-dmax': value
'name|count.dcount': value
'name|+step': value

eg:

'name|min-max': 'value' 通过重复 'value' 生成一个字符串,重复次数大于等于 min,小于等于 max。
'name|count': 'value' 通过重复 'value' 生成一个字符串,重复次数等于 count
Mock.mock({                        =>  {
   "string|1-10": "★"                    "string":"★★★★★★"
})//随机出现1到10个字符"★"              }

数据占位符DPD

占位符 只是在属性值字符串中占个位置,并不出现在最终的属性值中。占位符 的格式为:
@占位符号
@占位符(参数[,参数])

eg:

 {
    "自然数": "@natural",
    "浮点数": "@float",
    "日期": "@date",
    "时间": "@time",
    "标题": "@title",
    "中文名字": "@cname",
    "网址": "@url",
    "域名": "@domain",
    "邮箱": "@email",
    "段落": "@paragraph",
    "句子": "@sentence"
}
=>
{
    "自然数": 8077114183372796,
    "浮点数": -7509349163912364,
    "日期": "1970-03-14",
    "时间": "05:25:05",
    "标题": "Qgspmo Lcqiquof Kawo",
    "中文名字": "尤全信",
    "网址": "http://jcdtn.com/ppke",
    "域名": "chqykiyyq.co.uk",
    "邮箱": "c.lee@jackson.gov",
    "段落": "Ayooiokf llyhmsi owesieea yyishuzr rdnsl jexu vfrkrvuq icsb cclmce oofwykv qtcupiwv mgcclzb knltrto nhkg. Tcri rnxhtkj lzkoitbrg jss kxbtymnd ryyivbqn yjfv yydsldmw zuoy abfduhf chkbzzltdr tsfoh arkhtmbi. Hegjcqn vufnifrf opfxhbm nqkuoh chgclqvf irjpji uafmxjt fjhpjtby sybvjo xhstbpi tebcv pvfexmwgxx xfacci xnkqnij yysrepxvbr uermcpl cpoxyqzacm.",
    "句子": "Avtigmpj rgfocf iefnjw atuceo ild bledzp bwldvxihuh ledwbwpoo xrrdb kwewsm uoffu ymffqdwlk lidf qvdrpnc xmu txg mpheymd."
}

mockRespCode

在sosoapi中 内置了一个参数mockRespCode
可以通过设置不同的参数值来对应不同的页面回显
eg:
回显页面设置了200/300两个不同的页面

mockRespCode的值分别设为200和300来模拟正确和错误的回显页面

14
Nov

python+opencv进行简单的图像处理

事情是这样的

本着py狗好好的py不用为什么要用c++的想法
我开始了谷歌大法 python & 细化图像


环境

python2.7
openvc2.4.13.2


windows下安装opencv

OpenCV是一个C++库,用于实时处理计算机视觉方面的问题,涵盖了很多计算机视觉领域的模块。
OpenCV有两个Python接口,老版本的cv模块使用OpenCV内置的数据类型,新版本的cv2模块使用NumPy数组。

下载链接 https://opencv.org/releases.html
python2.7最好选对用openvc低一些的版本,我第一次安装选了高版本,结果无法适应,然后重装了。。。


Python_OpenCV环境配置

将opencv中的C:\opencv\build\python\2.7\x64下的cv2.pyd移动到python安装目录下的Lib\site-packages 中。
打开cmd,运行python


numpy&matplotlib

numpy和matplotlib,是两个比较简单易用的数据分析和可视化的库。
numpy

matplotlib


图像细化

图像的细化主要是针对二值图而言

所谓骨架,可以理解为图像的中轴,,一个长方形的骨架,是它的长方向上的中轴线,

圆的骨架是它的圆心,直线的骨架是它自身,孤立点的骨架也是自身。

骨架的获取主要有两种方法:

(1)基于烈火模拟

设想在同一时刻,将目标的边缘线都点燃,火的前沿以匀速向内部蔓延,当前沿相交时火焰熄灭,

火焰熄灭点的结合就是骨架。

(2)基于最大圆盘

目标的骨架是由目标内所有内切圆盘的圆心组成

我们来看看典型的图形的骨架(用粗线表示)

细化的算法有很多种,但比较常用的算法是查表法

细化是从原来的图中去掉一些点,但仍要保持原来的形状。

实际上是保持原图的骨架。

判断一个点是否能去掉是以8个相邻点(八连通)的情况来作为判据的,具体判据为:

1,内部点不能删除

2,鼓励点不能删除

3,直线端点不能删除

4,如果P是边界点,去掉P后,如果连通分量不增加,则P可删除

看看上面那些点。

第一个点不能去除,因为它是内部点

第二个点不能去除,它也是内部点

第三个点不能去除,删除后会使原来相连的部分断开

第四个点可以去除,这个点不是骨架

第五个点不可以去除,它是直线的端点

第六个点不可以去除,它是直线的端点

对于所有的这样的点,我们可以做出一张表,来判断这样的点能不能删除

我们对于黑色的像素点,对于它周围的8个点,我们赋予不同的价值,

若周围某黑色,我们认为其价值为0,为白色则取九宫格中对应的价值

对于前面那幅图中第一个点,也就是内部点,它周围的点都是黑色,所以他的总价值是0,对应于索引表的第一项

前面那幅图中第二点,它周围有三个白色点,它的总价值为1+4+32=37,对应于索引表中第三十八项

我们用这种方法,把所有点的情况映射到0~255的索引表中

我们扫描原图,对于黑色的像素点,根据周围八点的情况计算它的价值,然后查看索引表中对应项来决定是否要保留这一点


程序

# -*- coding: utf-8 -*-
"""
Created on Sat May 12 16:36:06 2018
"""
import cv2
 
#细化函数,输入需要细化的图片(经过二值化处理的图片)和映射矩阵array
#这个函数将根据算法,运算出中心点的对应值
def Thin(image,array):
    h,w = image.shape
    iThin = image
 
    for i in range(h):
        for j in range(w):
            if image[i,j] == 0:
                a = [1]*9
                for k in range(3):
                    for l in range(3):
                        #如果3*3矩阵的点不在边界且这些值为零,也就是黑色的点
                        if -1<(i-1+k)<h and -1<(j-1+l)<w and iThin[i-1+k,j-1+l]==0:
                            a[k*3+l] = 0
                sum = a[0]*1+a[1]*2+a[2]*4+a[3]*8+a[5]*16+a[6]*32+a[7]*64+a[8]*128
                #然后根据array表,对ithin的那一点进行赋值。
                iThin[i,j] = array[sum]*255
    return iThin        
    
#最简单的二值化函数,阈值根据图片的昏暗程度自己设定,我选的180
def Two(image):
    w,h = image.shape
    size = (w,h)
    iTwo = image
    for i in range(w):
        for j in range(h):
            if image[i,j]<180:
                iTwo[i,j] = 0 
            else:
                iTwo[i,j] = 255
    return iTwo
 
#映射表
array = [0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,\
         1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,\
         0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,\
         1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,\
         1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,\
         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
         1,1,0,0,1,1,0,0,1,1,0,1,1,1,0,1,\
         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
         0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,\
         1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,\
         0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,\
         1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,\
         1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,\
         1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,\
         1,1,0,0,1,1,0,0,1,1,0,1,1,1,0,0,\
         1,1,0,0,1,1,1,0,1,1,0,0,1,0,0,0]
 
#读取灰度图片,并显示
img = cv2.imread('./233.png',0) #直接读为灰度图像
cv2.imshow('image',img)
cv2.waitKey(0)
 
#自适应二值化函数,需要修改的是55那个位置的数字,越小越精细,细节越好,噪点更多,最大不超过图片大小
th3 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,55,2) #换行符号 \
cv2.imshow('iTwo',th3)
cv2.waitKey(0)
 
#获取自适应二值化的细化图,并显示
iThin = Thin(th3,array)
cv2.imshow('iThin',iThin)
cv2.waitKey(0)
 
#获取简单二值化的细化图,并显示
iTwo = Two(img)
iThin_2 = Thin(iTwo,array)
cv2.imshow('iTwo_2',iThin_2)
cv2.waitKey(0)
 
cv2.destroyAllWindows()


测试



问题

  1. 第一个问题是opencv安装问题,之前说了,python2.7要用低版本opencv,重装就完事儿。
  2. 第二个问题是程序一直报错
    error: (-215) size.width>0 && size.height>0 in function imshow
    结果是图像的路径问题,
    图片路径中“文件夹分隔符”使用的错误。
    将“\”改成“/”就好了~:blush:

14
Mar

CVE2018-100006漏洞复现

漏洞描述

什么是Electron?
Electron 是一款基于Chromium和Node.js ,使用HTML5、 Javascript 和 CSS构建跨平台桌面应用的开发框架。因为完美兼容 Node.js 包管理(npm)的大量功能和丰富的模块,并且相对于 native 降低了开发难度和迭代成本,因此受到了开发者的青睐,像Slack、Skype、网易云音乐、Github的Atom、Microsoft的VS Code均采用该框架开发。

2018年1月22日,Electron官方发布了对漏洞的安全公告

(https://electronjs.org/blog/protocol-handler-fix)

这是一个远程命令执行漏洞。
在受影响的应用注册了自定义 url 协议之后,攻击者可以利用这些伪协议,在浏览器等场景中远程通过恶意的 url 传递命令行参数执行任意命令,最终完全控制受害者的计算机.

由于其利用方式简单粗暴,执行效果理想,是一个危害很大的漏洞。由于 Electron 的流行,受影响的软件甚至包括 Atom 编辑器, GitHub 客户端, VSCode 编辑器, Slack 客户端,有道云音乐这样用户颇多的 Windows 桌面应用。


漏洞成因

漏洞要点:

1.基于构建的app登记了协议,即可以使用该协议直接打开应用程序。
2.影响win平台

原理浅析:

由官方的漏洞公告可知,该漏洞存在位置app.setAsDefaultProtocolClient()
在仓库中全局搜索
SetAsDefaultProtocolClient(electron/electron)
由于该漏洞仅影响Windows系统,则关注browser_win.cc#L212
该函数的主要的功能是实现注册表键值的注册。
通过查看注册表编辑器(运行regedit ),可以发现一项%1

运行PoC,点击构造好的超链接(payload),注册表中的%1则会替换成payload

Payload中的第一个双引号和“%1”前双引号闭合,Payload中的最后一个双引号和“%1”后双引号闭合,最终形成如下所示命令:

通过第3个参数带入Chromium实现命令执行:
--renderer-cmd-prefix=cmd.exe /c start calc


利用思路

  1. 程序开发时调用了存在漏洞的函数,实现用户自定义协议的注册,拿我这个来说注册了test协议,那当用户访问test协议下的资源时,就会启动该程序访问(test://xxx)
    app.setAsDefaultProtocolClient('test')

  2. 程序启动时会在注册表中注册键值(%1是占位符,用于接收用户输入的参数)
    "E:\elec_rce.exe" "%1"

  3. 执行PoC时,通过刚刚程序注册的test://自定义协议触发
    test://?" "--no-sandbox" "--renderer-cmd-prefix=cmd.exe /c start calc

  4. payload带入占位符%1,同时闭合双引号,通过后续的参数--renderer-cmd-prefix,传递至Chromium,实现命令执行


漏洞复现

样本1:

环境搭建:
Microsoft Windows10
Electron 1.7.8
https://github.com/CHYbeta/CVE-2018-1000006-DEMO
里面的文件有main.js、index.html、package.json

自己打包成exe应用,生成有漏洞的版本,以版本1.7.8为例:

本地写一个触发的html,其中的协议名称要与之前的设置一一对应

当你点击链接时,会触发这个RCE,实现命令执行,弹出计算器。

样本2:

环境搭建:
Microsoft Windows10
Electron 1.7.8
网易云音乐客户端2.0

由于我们知道网易云客户端用到的协议是orpheus://


影响范围

Electron < 1.8.2-beta.4、1.7.11、1.6.16 的版本


解决方案

1.升级至1.8.2-beta.4、1.7.11、1.6.16版本
官方补丁:
https://github.com/electron/electron/commit/c49cb29ddf3368daf279bd60c007f9c015bc834c
2.不升级的话,可以在调用app.setAsDefaultProtocolClient()函数时,增加--参数(代表命令行选项的结束,类似注释?),避免Chromium解析更多的选项

25
Jan

微信跳一跳(adb+py)

事情是这样的:
zzq发了一张图片给我

然后我就...
是键盘先动的手!!!


环境

win10+夜神模拟器+三星S8+wechat_jump.py


win10安装adb

折腾了很久,其实直接下载下来解压就行了
adbshell手册http://adbshell.com/
我直接放在桌面了 因为不常用adb(/Desktop/adb)
这里有个坑 需要先看一下adb的版本号adb version 必须要和模拟器nox_adb版本号相同,不然执行会要报错(后面要讲QAQ)


夜神模拟器

必须开启开发者模式
设置-关于平板电脑-多次点击版本号
退回到设置目录-开发者选项-USB调试模式
然后在win10本机命令行执行adb devices
发现adb连不上模拟器
报错信息:

C:\Users\A1in\Desktop>adb devices
List of devices attached
adb server version (31) doesn't match this client (36); killing...
* daemon started successfully *

解决方案:

  1. 关掉adb和夜神模拟器,在任务管理器下,结束adb.exe和nox_adb.exe这两个进程
  2. 找到adb的目录和夜神模拟器的目录,将夜神模拟器的adb.exe复制到adb的目录下
  3. 这样就adb目录下的adb.exe和模拟器下的adb.exe文件就完全同步了,版本号也一致了

再次执行adb devices
发现虽然不报错了 但是还是显示无配置连接
突然想到翻夜神文件夹时,在\Nox\bin文件夹自带了nox_adb.exe
尝试直接用nox_adb.exe 连接夜神 直接成功了
orz 我绕了地球一圈后来发现要找的东西就在脚下...
nox_adb连接模拟器成功,模拟器微信也安装了
然后打开微信-进入跳一跳 发现闪退 闪退 闪退???:alien:
网上的方法都尝试过了(关闭root/调试显卡渲染模式/性能设置/机型设置)
后来知道好像是夜神模拟器中微信跳一跳已封禁...


adb+S8=起飞

然后我妥协了...
向凌同学借了他的S8...
adb devices秒连

adb shell 秒root

(当然S8也是要开启开发者模式-USB调试模式的)


wechat_jump.py

# coding: utf-8
import math
import os
import tempfile
import time
from functools import reduce
from PIL import Image

BACKGROUND_POS = (40, 500)
DISTANCE_TO_TIME_RATIO = 1.35
SCREENSHOT_PATH = tempfile.gettempdir() + "/screenshot.png"

def calculate_jump_distance():
    im = Image.open(SCREENSHOT_PATH)
    background_rgb = im.getpixel(BACKGROUND_POS)
    role_pos_list = None
    vertex1_pos = None
    block_background_rgb = None
    vertex2_pos = None
    role_line_flag = True
    for y in range(BACKGROUND_POS[1], im.height):
        if role_pos_list and role_line_flag:
            break

        role_line_flag = True
        vertex2_line_flag = True
        for x in range(BACKGROUND_POS[0], im.width):
            current_rgb = im.getpixel((x, y))
            next_rgb = im.getpixel((x + 1, y)) if x + 1 < im.width else (0, 0, 0)

            # 识别顶点1
            if x > BACKGROUND_POS[0] and y > BACKGROUND_POS[1] and not vertex1_pos and not is_similar(background_rgb, current_rgb) and is_similar(current_rgb, next_rgb):
                vertex1_pos = (x, y)
                block_background_rgb = current_rgb

            # 识别顶点2
            if block_background_rgb and vertex2_line_flag and is_similar(current_rgb, block_background_rgb, 5):
                vertex2_line_flag = False
                if vertex2_pos:
                    if x < vertex2_pos[0] and vertex2_pos[0] - x < 20 and y - vertex2_pos[1] < 20:
                        vertex2_pos = (x, y)
                else:
                    vertex2_pos = (x, y)

            # 识别小人
            if is_part_of_role(current_rgb):
                if role_line_flag:
                    role_pos_list = []
                    role_line_flag = False
                role_pos_list.append((x, y))

    if len(role_pos_list) == 0:
        raise Exception('无法识别小人位置!!!')
    pos_sum = reduce((lambda o1, o2: (o1[0] + o2[0], o1[1] + o2[1])), role_pos_list)
    role_pos = (int(pos_sum[0] / len(role_pos_list)), int(pos_sum[1] / len(role_pos_list)))
    destination_pos = (vertex1_pos[0], vertex2_pos[1])
    return int(linear_distance(role_pos, destination_pos))

def is_part_of_role(rgb):
    return 53 < rgb[0] < 59 and 57 < rgb[1] < 61 and 95 < rgb[2] < 103
def linear_distance(xy1, xy2):
    return math.sqrt(pow(xy1[0] - xy2[0], 2) + pow(xy1[1] - xy2[1], 2))
def is_similar(rgb1, rgb2, degree=10):
    return abs(rgb1[0] - rgb2[0]) <= degree and abs(rgb1[1] - rgb2[1]) <= degree and abs(rgb1[2] - rgb2[2]) <= degree
def screenshot():
    os.system("adb shell screencap -p /mnt/sdcard/screencap.png")
    os.system("adb pull /mnt/sdcard/screencap.png {} >> {}/jump.out".format(SCREENSHOT_PATH, tempfile.gettempdir()))
def jump(touch_time):
    os.system("adb shell input swipe 0 0 0 0 {}".format(touch_time))
def distance2time(distance):
    return int(distance * DISTANCE_TO_TIME_RATIO)

if __name__ == '__main__':
    count = 1
    while True:
        screenshot()
        distance = calculate_jump_distance()
        touch_time = distance2time(distance)
        jump(touch_time)
        print("#{}: distance={}, time={}".format(count, distance, touch_time))
        count += 1
        time.sleep(1)

运行需要安装PIL(pip install Pillow)


你想要多少分呀

24
Jan

kali翻墙 (ss+proxychains)

安装命令行界面的Shadowsocks

终端输入:
apt-get install python-pipsudo pip install shadowsocks
创建配置文件-终端输入:
gedit /etc/shadowsock/config.json

加入下面的配置内容,并补全配置信息

{ "server":"服务器地址", 
"server_port":服务器端口号, 
"local_address": "127.0.0.1", 
"local_port":1080,
"password":"密码", 
"timeout":300, 
"method":"加密方式",
"fast_open": true,
"workers": 1}

终端启动客户端:
sslocal -c /etc/shadowsocks/config.json


配置proxychains

打开proxychains配置文件:
leafpad /etc/proxychains.conf

将socks4 127.0.0.1 9095改为socks5 127.0.0.1 xxxx
//xxxx改为你自己的端口

去掉dynamic_chain前面的注释符

添加代理服务器列表在最下方这, 默认是socks4 xxxx xxx
改成sock5 127.0.0.1 1080


测试代理服务是否正常

终端输入:proxyresolv www.google.com

此时执行会出现命令未找到

终端输入:cp /usr/lib/proxychains3/proxyresolv /usr/bin/

然后再次执行 proxyresolv www.google.com
//在执行过sslocal -c /etc/shadowsocks/config.json之后,这时候ss的命令界面应该是正在运行的

返回ok,说明配置正确,可以愉快的跨栏了。^ ^


使用ProxyChains 启动firefox

终端输入:proxychains firefox //启动火狐浏览器


使用ProxyChains代理其他程序

终端输入:proxychains msfconsole//启动msf

终端输入:proxychains python shodanwave.py//代理终端