打卡打卡,忘记一次扣你一天工资没商量,坑
在分公司领导及同事的强烈要求下,将公司总部的打卡系统进行破解。
破解历程:
找出公司打卡的方式-----利用电脑每天打卡-------利用django进行手机打卡------自动打卡。
步骤1:
我公司利用移动的和我信app进行打卡,需要登入移动的和我信app,之后在里面进行打卡。
分析如下:
1.我公司的打卡系统网页直接和和我信的接口进行关联,等于是登入和我信就等于登入我公司的打卡系统。
2.等于是打卡的cookie可能是固定的。
利用工具就行数据抓取,我这边使用的是charle,软件教程自己百度。通过电脑共享wifi,设置代理,通过手机连接该代理,连接完成,手机打开公司软件,进行打卡,点击打开的时候抓取打卡地址,及post上传的数据,及cookie。
抓取得信息如下:
http打卡post地址:http://******.******.com/DaKa/DaKaHome/DaKa
data数据:
var data = {
time: 2018-03-08:15:23,
address: *****,
jingdu: "****",
weidu: "*****"
};
网页反馈的数据,通过分析js文件得到信息如下。
反馈代码:
ok001: 打卡成功
ok002:打卡异常
ok003:打卡异常
反馈的cookie地址:
UserloginNameCookie=18179*******
通过以上信息得知结果如下:
- 上传打卡时间,地址,经度跟纬度。
- 通过反馈的结果可以得知是否打卡成功。
- 通过cookie得知,cookie值就是UserloginNameCookie=+手机号
信息得到后,通过网址进行测试:
http://www.atool.org/httptest.php
输入网址,参数,cookie,点击发送请求,得出反馈结果为ok001。
打卡成功,运行一段时间后发现都没有问题,
但是每次上班下班不可能打开电脑进行打卡,特别麻烦。下面就是django打卡的开发。
首先,利用pycharm自动创建一个django框架。
创建完成后设置setting.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'dakamanager',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'kamanager.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')]
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'kamanager.wsgi.application'
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = True
STATIC_URL = '/static/'
# STATIC_ROOT = os.path.join(BASE_DIR, 'collectstatic')#此处必须,为新添加
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
STATIC_ROOT = os.path.join(BASE_DIR, "static_all")
urls.py设置如下:
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r"^$", views.Index, name="index"),
url(r"^login/",views.Login,name = "login"),
#url(r"^ceshi/",views.ceshi,name = "ceshi"),
#采用ajax异步登入
url(r"^login_daka_ajax/",views.login_daka_ajax,name = "login_daka_ajax"),
#采用ajax异步打卡
#url(r"^yanzhengma_ajax/",views.yanzhengma_ajax,name = "yanzhengma_ajax"),
]
models.py文件展示如下:
from django.db import models
# Create your models here.
class daka(models.Model):
phone = models.CharField(max_length=12, verbose_name="手机号", blank=True)
cookie = models.CharField(max_length=999, verbose_name="cookie", blank=True)
name = models.CharField(max_length=999, verbose_name="姓名", blank=True)
views.py文件如下:
from django.shortcuts import render
# Create your views here.
# -*- coding: utf-8 -*-
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
from django.template.loader import get_template
from django.shortcuts import render
from django.template import RequestContext, loader
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.db.models import Q
import json
from dakamanager import models
from dakamanager.get_jiancha import select_cookie,POST_daka
# Create your views here.
def Index(request):
return render(request,"index.html")
def Login(request):
#查询数据库内是否存在手机号,不存在联系管理员,存在时反馈ok,跳出打卡按钮
ret = {"status": True, "error": None, "data": None,"cookie":True}
if request.method == "POST":
obj = models.daka.objects.filter(phone=request.POST.get("phone"))
if not obj:
ret["status"] = False
ret["error"] = "请联系管理员"
else:
#查询cookie是否可用,能否利用cookie登入网站。
if select_cookie(obj[0].cookie):
ret["cookie"] = True
else:
ret["cookie"] = False
print(ret)
return HttpResponse(json.dumps(ret))
#通过ajax异步点击打卡,打卡反馈数据,成功或者失败
def login_daka_ajax(request):
ret = {"status": True, "error": None, "data": None, "cookie": True}
if request.method == "POST":
obj = models.daka.objects.filter(phone=request.POST.get("phone"))
if POST_daka(obj[0].cookie):
pass
else:
ret["status"] = False
print(ret)
return HttpResponse(json.dumps(ret))
最重要的打卡调用文件get_jiancha.py
# -*- coding: UTF-8 -*-
import urllib
import http.cookiejar
import time,re,json
from pacong.zuobiao import zuobiao
def Re(res,total,id = "1"):
if id == "1":
data = re.findall(str(res),total)
if id == "2":
data = re.findall(str(res),total,re.S)
return data
#打卡,传入cookie
def POST_daka(cookie):
a = zuobiao()
URL_ROOT = 'http://******.&&&&&.com/DaKa/DaKaHome/DaKaRcsA'
timename = time.strftime("%H:%M")
values = {'time': str(timename), 'address': u'#########999号', "jingdu": str(a[0]), "weidu": str(a[1])}
cookie_headers = {
"Cookie": cookie,
}
URL_ROOT = 'http://******.YYYYYYY.com/DaKa/DaKaHome/DaKaRcsA'
cookie = http.cookiejar.LWPCookieJar()
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
postdata = urllib.parse.urlencode(values).encode()
try:
request = urllib.request.Request(URL_ROOT, postdata, cookie_headers)
get_response1 = opener.open(request)
# print(get_response1.read().decode(),type(get_response1.read().decode()))
if Re("001",str(get_response1.read().decode())):
ret = True
else:
ret = False
except Exception as e:
ret = False
return ret
#查看 cookie是否可用,可用的话 开始打卡
def select_cookie(cookie):
ret = True
cookie_headers = {
"Cookie": cookie,
}
cookie = http.cookiejar.LWPCookieJar()
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
#利用cookie查询网站是否能登入
get_url = 'http://######.########.com/DaKa/DaKaHome/DaKaRCS'
get_request = urllib.request.Request(get_url, headers=cookie_headers)
try:
get_response = opener.open(get_request)
data = get_response.read().decode()
k = Re("<p><b>请稍等...</b></p>",data)
if k:
ret = True
else:
ret = False
except Exception as e:
ret = False
return ret
还有个坐标随机值zuobiao.py
#主要让坐标进行随机生成,会在打卡位置的随机100米范围内,这样每次打卡的位置都完全不一样。
import random
def zuobiao():
a = random.randint(11,99)
b = random.randint(11,99)
c = format(str(*******) + str(a))
d =format(str(*******) + str(b))
return [c,d]
index.html文件展示,里面还设计扩展手机验证码登入,但用不上。
<!DOCTYPE html>
<html lang="en">
<head>
<meta content="text/html" charset="utf-8">
<title>打卡系统</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
{# <meta name="viewport" content="width=device-width, initial-scale=1">#}
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="stylesheet" type="text/css" href="/static/css/bootstrap.min.css">
</head>
<body>
<style>
.hide{
display:none;
}
</style>
<div>
<div class="col-md-offset-4 col-md-4 col-xs-12" style="margin-top: 10%">
<div class="text-center">
<h1>打卡系统</h1>
</div>
<div class="center-block">
<input type="text" class="form-control" name="phone" id="phone">
</div>
<div>
<h4 class="text-center bg-danger" id="error"></h4>
</div>
<div class="col-md-offset-5 col-md-4 col-xs-offset-4" style="margin-top: 30px">
<button type="submit" class="btn btn-primary" id="dengru">登 入</button>
</div>
<div>
<input type="text" id="yanzhengma" class="hide">
<button type="submit" id="yzmdaoru" class="hide">获 取 验 证 码</button>
<button type="submit" id="dakadengru" class="hide">登入打卡系统</button>
</div>
<div class="col-md-offset-5 col-md-4 col-xs-offset-4" style="margin-top: 30px">
<button type="submit" id="daka" class="hide btn btn-info ">打 卡</button>
</div>
<div id="app">
<p>{{ message }}</p>
</div>
</div>
</div>
</body>
<script src="/static/js/jquery.min.js"></script>
<script>
$("#dengru").click(function () {
var phone = $("#phone").val()
$.ajax({
url: "{% url "login" %}",
type: 'POST',
data:{"phone":phone},
success: function(data){
var obj = JSON.parse(data);
if(obj.status){
$("#dengru").addClass("hide")
if (obj.cookie){
$("#daka").removeClass("hide")
$("#error").text()
}else{
$("#yzmdaoru").removeClass("hide")
$("#yanzhengma").removeClass("hide")
$("#dakadengru").removeClass("hide")
}
}else{
$("#error").text(obj.error)
};
}
});
});
$("#daka").click(function () {
var phone = $("#phone").val()
$.ajax({
url: "{% url "login_daka_ajax" %}",
type: 'POST',
data:{"phone":phone},
success: function(data){
var obj = JSON.parse(data);
if(obj.status){
$("#error").text("打卡成功")
}else{
$("#error").text("打卡失败")
};
}
});
});
$("#yanzhengma").click(function () {
var phone = $("#phone").val()
$.ajax({
url: "{% url "yanzhengma_ajax" %}",
type: 'POST',
data:{"phone":phone},
success: function(data){
var obj = JSON.parse(data);
if(obj.status){
$("#yzmdaoru").addClass("hide")
}else{
};
}
});
});
</script>
</html>
关键代码基本已经完成,上图。用的是bootstrap,所以会根据手机分辨率进行自动响应,以后可以很happy的在家里打卡在上班啦。
登入界面 打卡界面
打卡成功界面
后期扩展:
这个功能基本实现啦。但也有很多缺陷,比如忘记啦打卡。
后期有空扩展下:
- 方法一:
直接利用django celery每天定时任务打卡,这个功能很容易实现,傻瓜化,但哪天家里的服务器挂啦都不知道,导致没打卡,不合适。 - 方法二(还是利用celery,有空实现下,这个也简单):
每天在上班的前十分钟对打卡记录进行检测,检测没打卡,则自动补上打卡记录。只要每天打卡时自动生成一个时间。并且检测的时候对时间进行比对,确认异常的进行打卡。
网友评论