小橙子小朋友是社实的,社实需要获得本科生的信息,学校也同意他们去hub系统上去导入,但是hub系统的外包公司不同意这件事情。
于是他就想绕过外面公司那层,直接获取hub系统的信息,至少学校也同意了,这就变成一件艹hub的游戏了,呵呵……
hub需要验证码才能登录,但是小橙子在这个事情上有些拙计,我就祝他一臂之力。
说到验证码破解,我在之前已经实现了,用的是tesseract-ocr这套开源的软件,在linux上搭建了一个示例,用来破解某些学校招生信息网的验证码。
后来这个系统没有得到实用,重装服务器的时候,装掉了。

现在重新拾起来,也不是一个难事。搭建服务器系统主要有一下几步:

安装前必备的包

yum install libpng12-dev
yum install libjpeg62-dev
yum install libtiff4-dev
yum install automake

wget  http://www.leptonica.org/source/leptonlib-1.67.tar.gz
tar -zxvf  leptonlib-1.67.tar.gz
cd leptonlib-1.67
./configure
make
make install

安装tesseract-ocr

wget http://tesseract-ocr.googlecode.com/files/tesseract-3.01.tar.gz
tar -zxvf  tesseract-3.01.tar.gz
cd tesseract-3.01
./autogen.sh
./configure
make
make install

不出意外的话应该可以编译成功的
在centos上总是出问题
之前是用的3.02版的,但就是编译不通过,谷歌坏了,所以网上找不到方案。
换用3.01版的,就不会有太多问题。

下载识别数据

wget http://tesseract-ocr.googlecode.com/files/tesseract-ocr-3.01.eng.tar.gz
tar xvf tesseract-ocr-3.01.eng.tar.gz
mv tesseract-ocr/tessdata/* /usr/local/share/tessdata/

测试一下tesseract,让tesseract识别这幅图片中的验证码
hubcode

wget http://blog.gerpayt.cn/wp-content/uploads/2014/06/hubcode.jpg
tesseract hubcode.jpg temp
cat temp.txt

得到72204,这说明tesseract-ocr安装成功了。

接下来写一个web接口。

<?php
//ini_set('display_errors','On');
//error_reporting(E_ALL);
if (@$_FILES['image'])
{
    $path = dirname($_SERVER["SCRIPT_FILENAME"]);
    move_uploaded_file(@$_FILES['image']['tmp_name'],$path.'/fuckhub.jpg');

    $imgsrc="data:".@$_FILES['image']['mime'].";base64,".base64_encode(file_get_contents("{$path}/fuckhub.jpg"));
    $ex = "{$path}/fuckhub.jpg {$path}/fuckhub";
    //print $ex;

    $socket = socket_create(AF_UNIX, SOCK_STREAM, 0);
    $connection =@socket_connect($socket,"/tmp/tesseract.sock");
    if ($connection)
    {
        socket_write($socket, $ex);
        $buffer = socket_read($socket, 1024);
        //socket_recvmsg($socket,$buffer);
        socket_close($socket);
        //print $buffer;
        $code =  trim(@file_get_contents($path.'/fuckhub.txt'));
    }
    else
    {
        print "Socket error!";
    }
    @unlink($path.'/fuckhub.jpg');
    @unlink($path.'/fuckhub.txt');
    if (@$_GET['api'])
    {
        echo $code;
        die();
    }
}
?>
<html>
<head>
</head>
<body>
fuckhub
<form action='' method='post' enctype="multipart/form-data">
<input type='file' name='image'/> <br />
<input type='submit' />
</form>
<img src="<?php print @$imgsrc ?>">
<input name="result" value="<?php print @$code; ?>">

</body>
</html>

因为php文件是由www用户来执行的,所以直接调用tesseract命令是失败的,处理方法与之前的一些类似,就是在后台增加一个常驻进程,进程的用户是root,网页通过unixsocket和常驻程序进行通信。于是就可以通过php来执行tesseract命令了。
后台常驻程序

from daemon import daemonize
import socket,os,commands,stat

def main():
    sockfile="/tmp/tesseract.sock"
    sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    if os.path.exists(sockfile):
        os.unlink(sockfile)
    sock.bind(sockfile)
    sock.listen(5)
    os.chmod(sockfile,stat.S_IRWXU|stat.S_IRWXG|stat.S_IRWXO)
    while True:
        connection,address = sock.accept()
        param = connection.recv(1024)
        (rc,rs) = commands.getstatusoutput('/usr/local/bin/tesseract ' + param)
        connection.send(rs)
    connection.close()

if __name__ == "__main__":
    daemonize()
    main()

以下是daemon.py

#!/usr/bin/python
#coding:utf-8

import sys
import os

def daemonize(stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
    try:
        pid = os.fork()
        if pid > 0:
            sys.exit(0)
    except OSError, e:
        sys.stderr.write("fork #1 failed: (%d) %s\n" % (e.errorno, e.strerror))
        sys.exit(1)

    os.chdir('/')
    os.umask(0)
    os.setsid()

    try:
        pid = os.fork()
        if pid > 0:
            sys.exit(0)
    except OSError, e:
        sys.stderr.write("fork #2 failed: (%d) %s\n" % (e.errorno, e.strerror))
        sys.exit(1)

    for f in sys.stdout, sys.stderr:
        f.flush()

    si = file(stdin, 'r')
    so = file(stdout, 'a+')
    se = file(stderr, 'a+', 0)
    os.dup2(si.fileno(), sys.stdin.fileno())
    os.dup2(so.fileno(), sys.stdout.fileno())
    os.dup2(se.fileno(), sys.stderr.fileno())

启动后台程序后,就可以通过访问php网页,从表单中提交验证码图片,来得到验证码中的数字了。

小橙子说这样还不过瘾,最好搞个接口,我就让他用curl模拟post,网址上带个?api=1的参数,就只返回结果了。
一个接口,在本地调用

<?php
$url="http://work.gerpayt.cn/decaptcha/fuckhub.php?api=1";
$data=array('image'=>'@test.jpg');
$ch = curl_init(); //初始化curl
curl_setopt($ch, CURLOPT_URL, $url);//设置链接
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//设置是否返回信息
curl_setopt($ch, CURLOPT_POST, 1);//设置为POST方式
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);//POST数据
$response = curl_exec($ch);//接收返回信息
if(curl_errno($ch)){//出错则显示错误信息
    print curl_error($ch);
}
curl_close($ch); //关闭curl链接
echo $response;//显示返回信息

大功告成,以后艹hub就方便了。。。

参考

http://hub.hust.edu.cn/index.jsp

http://work.gerpayt.cn/decaptcha/fuckhub.php

http://blog.yorkgu.me/2012/01/30/compile-and-install-tesseract-orc-on-centos/

Leave a reply