吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2548|回复: 8
收起左侧

[其他转载] 解析某网络教学平台登录时的明文加密方法并使用python实现代码复现

[复制链接]
we37 发表于 2021-4-18 22:13
不知道标题说清楚了没(^_^)。
上学期考完试,因为成绩是一门一门的出来,经常都要去网络教学平台登录查看成绩出没出(那种不知道自己是否挂科的煎熬感),我嫌烦而且刚好学完爬虫,就想着看能不能写个脚本实现一键查成绩的功能,当时没有具体的学过前端代码,但因为有c的基础也算是能看出来一点,然后抓包解析,一顿瞎操作,明文具体怎么加密的没看懂,但是找到了加密完的密文和发送的url(嘿嘿),然后数据清洗,功能这不就实现了吗,然后,就没有然后了,功能都实现了,那还然后个屁。
但是最近我自己的网站因为是http明文传输,也不好加证书实现https,所以我就想,用户数据安全肯定得保证啊,得想办法搞一套加密方法回来,这样就又记起了我学校的这套当时没看懂的加密。
通过打断点,看代码解析完之后,我发现其实还蛮简单的。所以想将这个加密方法分享给大家。好了,废话说了这么多了(不是),直接上源码。
-----------------------------------------------------------------------------------------------
以下解析实属小白的我玩玩,有问题希望大神指出来(^_^)感激不尽。
本文适合有一点前端知识的同学阅读,大家加油学啊!!!!






form表单
[HTML] 纯文本查看 复制代码
<form id="loginForm" name="loginForm" action="/Logon.do?method=logon" method="post">

	<ul id="ul1" >

		<li class="box_bt"><img class="img-responsive" src="/css/images/user_icon.png"  style="float:left;margin:8px 8px 0 0">用户登录</li>

		<li class="input-group input_li">

			  <span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>

			  <input type="text" class="form-control" id="userAccount" name="userAccount" placeholder="请输入账号" value="123" autofocus>

		</li>

		<li class="input-group input_li">

			  <span class="input-group-addon" id="basic-addon1"><i class="glyphicon glyphicon-lock"></i></span>

			  <input type="password" class="form-control" id="userPassword" name="userPassword" placeholder="请输入密码" value="">

		</li>

		<li class="input_li">

			<button type="button" class="btn btn-primary login_btn">登   录</button>

		</li>

	</ul>

	<input name="encoded" id="encoded" type="hidden" value=""/>

</form>




js代码
[JavaScript] 纯文本查看 复制代码
function login() {

	if($("#userAccount").val() == "") {

		$("#showMsg").text("请输入账号");

		$("#userAccount").focus();

		return false;

	}

	if($("#userPassword").val() == "") {

		$("#showMsg").text("请输入密码");

		$("#userPassword").focus();

		return false;

	}

	

		

		var strUrl = "/Logon.do?method=logon&flag=sess";

	



	$.ajax( {

		url:strUrl,

  		type:"post",

  		cache:false,

		dataType:"text",

		success:function(dataStr) {

			if(dataStr=="no"){

				return false;

	 		}else{

	 			var scode=dataStr.split("#")[0];

		     	var sxh=dataStr.split("#")[1];

		     	var code=document.getElementById("userAccount").value+"%%%"+document.getElementById("userPassword").value;

			 	var encoded="";

				for(var i=0;i<code.length;i++){

					if(i<20){

						encoded=encoded+code.substring(i,i+1)+scode.substring(0,parseInt(sxh.substring(i,i+1)));

					    scode = scode.substring(parseInt(sxh.substring(i,i+1)),scode.length);

					}else{

					    encoded=encoded+code.substring(i,code.length);

					    i=code.length;

					}

				}

				document.getElementById("encoded").value=encoded;

				if("logon"!="logonLdap"){

					document.getElementById("userPassword").value="";

				}



				document.getElementById("loginForm").submit();

	 		}

		},

		error:function() {

	 		alert("计算异常!");

		}

  	});

}




form表单我过滤了一遍,将一些与本文无关的代码剔除。看着很简单,两个输入框,一个提交按钮,最下面还有个隐藏的输入框,不知道是干什么用的,不用纠结,后面肯定有用到,接着往下看。

js代码中,上面两个if判断都是做输入框非空处理的,不用关注,接着看有个strUrl,然后使用ajax异步提交了一个post请求,但是: 可以看到该请求体中没有data字段,也就是没有将我们的账号密码提交上去,说明提交还在后面,接着往下看,请求success之后,从服务器拿到了一个dataStr,然后做了一步判断,不用说,这里返回no的几率很小,所以不用管,接着看,到了下面,我们发现它将dataStr通过’#‘分开了,那么这里就有点疑问了,dataStr到底是个啥??不解决这个问题我们再往下看也没用。所以怎么办才能拿到dataStr呢?
     
         打断点

打断点可以说是一个基础而且十分有用的技能了,至少我写爬虫是经常需要打断点的。

断点1.png

通过打断点,我们可以看到dataStr很清晰的展现在我们面前,
[JavaScript] 纯文本查看 复制代码
 

	dataStr = "8321akd3k0013M7cQ0Dv1Y749315N3f2Sxy762W213#13122313321123323321"

	scode = "321akd3k0013M7cQ0Dv1Y749315N3f2Sxy762W213"

	sxh = "13122313321123323321"

	code = "123%%%123"    # code就是我们的  账号+"%%%"+密码

	

看到这里,一些基本的变量已经知道了,强烈推荐大家自己试着解一下。

然后又定义了一个encoded,我们应该能猜到encoded应该是用来存放加密完之后的密文的。

接下来看for循环里的if体内,

       
[JavaScript] 纯文本查看 复制代码
encoded=encoded+code.substring(i,i+1)+scode.substring(0,parseInt(sxh.substring(i,i+1)));

       
  • substring ?? 没见过,没关系,百度一下,百度到结果是字符串截取,括号内是字符串下标,不包括后边的下标。
  • parseInt ?? 没见过,没关系,百度一下,字符串转为数值类型。

-----------------------------------------------------------------------------------------
那么第一次for循环就清楚了:

code.substring(i, i + 1)   就是将code取第一个字符
scode.substring(0,parseInt(sxh.substring(i,i+1)))  就是先取sxh的第一个字符,然后将他转成数值,再从scode中取到0-这个数字范围内的字符,在第一次循环中表现为scode.substring(0, 1) 也就是取scode的第一个字符。

接下来的这个语句:

       
[JavaScript] 纯文本查看 复制代码
scode = scode.substring(parseInt(sxh.substring(i,i+1)),scode.length);

       
很简单的置换,将scode中“已经使用了的字符”进行删除。

那下面的else是什么意思啊?

       
[JavaScript] 纯文本查看 复制代码
encoded=encoded+code.substring(i,code.length);
	i=code.length;

       
意思就是将code中大于20的之后的字符一口气全部加到encoded后面,然后直接退出for循环(即第二条语句的意思,换了一种写法,但是和break意思一样)

for循环完成之后有这样一条语句:

       
[JavaScript] 纯文本查看 复制代码
document.getElementById("encoded").value=encoded;

       
奥,原来是将加密后的密文encoded赋值给form表单中的被隐藏的那个输入框啊,
       
       
[JavaScript] 纯文本查看 复制代码
document.getElementById("userPassword").value="";


将密码框的文本清空,最后将form表单submit提交。
这就很好解释了在传输过程中如何保证数据安全,以及后端如何拿到密文。


这样整个过程就全部分析完成了。

接下来的python代码复现也是很好完成了,

[Python] 纯文本查看 复制代码
scode = "321akd3k0013M7cQ0Dv1Y749315N3f2Sxy762W213"

sxh = "13122313321123323321"

account = input('账号:')

password = input('密码:')

encoded = ''

code = f'{account}%%%{password}'

for i in range(len(code)):

	if i < 20:

		// encoded=encoded+code.substring(i,i+1)+scode.substring(0,parseInt(sxh.substring(i,i+1)));

		encoded = encoded + code[i] + scode[0:int(sxh[i])]

		// scode = scode.substring(parseInt(sxh.substring(i,i+1)),scode.length);

		scode = scode[int(sxh[i]):]

	else:

		// encoded=encoded+code.substring(i,code.length);

		encoded = encoded + code[20:]

		break

data = {

	'userAccount': accouont,

	'encoded': encoded,

}

res = requests.post(url='...',data=data,headers=header)



好了,完成!(从这里也能看出我们python代码的简洁,python之禅)


但是仅仅这样就够了吗?
*****************
我们在分析ajax异步请求的时候,知道了异步请求会返回一个dataStr,既然不是本地变量,那肯定会根据后端的变化而变化,所以这个变量我们肯定是要单独请求一次的。
*****************
我们在程序前面添上:

[Python] 纯文本查看 复制代码
	dataStr = request.post(url='/Logon.do?method=logon&flag=sess',headers=header).text

	scode = dataStr.split("#")[0]

	sxh = dataStr.split("#")[1]

       
这样差不多就完成了。
这应该算是一个非常简单的逆向,但是我还是蛮有收获的。
学习永无止境,人生苦短,我用python  (嘻)

免费评分

参与人数 6吾爱币 +12 热心值 +6 收起 理由
jjjzw + 1 + 1 用心讨论,共获提升!
electrical + 1 + 1 热心回复!
长河落 + 1 + 1 用心讨论,共获提升!
chinawolf2000 + 1 + 1 热心回复!
zecore + 1 + 1 谢谢@Thanks!
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

xfmiao 发表于 2021-4-18 22:31
厉害,分析的到位
z137465707 发表于 2021-4-18 23:07
zecore 发表于 2021-4-19 00:01
taijizsf666 发表于 2021-4-19 07:52
楼主厉害,加油
Alexxxx 发表于 2021-4-19 09:30
学习学习!!!!
Amichen 发表于 2021-4-19 10:31
写的很详细,666666
头像被屏蔽
dongse 发表于 2021-4-19 10:36
提示: 作者被禁止或删除 内容自动屏蔽
bwuaich 发表于 2021-4-19 11:25
分析详细;  欢迎分析讨论交流,吾爱破解论坛有你更精彩
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-20 03:57

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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