> 文档中心 > C#WinForm实现雷速网站逆向

C#WinForm实现雷速网站逆向

目录

前言

一、查找绘制前的关键代码

二、解剖数据加密过程

三、通过 C# WinForm 进行获取调用

总结


前言

提示: 本文仅用于学习分享,禁止用于任何违法行为,如有侵权,请联系删除。 

目标网址:足球赛果_足球联赛赛果_足球比赛赛果-雷速体育雷速体育足球赛果提供最新最全的欧洲杯、世界杯、五大联赛、中超等国内国际大小足球比赛的赛事结果,看足球赛果首选雷速体育!https://live.leisu.com/wanchang

从上图中可以看到,页面中显示的数据变成了 Canvas 标签,可以理解为绘制成了一张图片,从dom节点中无法得到可编辑的数据。


一、查找绘制前的关键代码

我们在开发者面板下,直接快捷键 Ctrl+Shift+F 全局搜索 qcbf 

 可以看到,通过检索我们找到了比较贴和页面呈现效果的代码,通过观察代码,发现这个js文件中的代码可读性不是很好,如下:

在代码中看到经常用到 _x26388 这样的代码出现,那_x26388是什么呢,通过本页Ctrl+F检索 ,不难发现实际_x26388 是一个数组变量

 这样就知道了里面方法的调用或者字符引用都是通过数组索引方式去获取调用,并且在这个JS中发现了这样的代码,有Vue经验的朋友不难发现,这是一个Vue组件,_x26388[1]就是组件的名称 match_layout_wc,那么页面要显示数据,必定要调用这个组件进行一个渲染,我们直接检索 match_layout_wc 找到调用的地方

 上图我们找到了调用组件的位置,这里看到代码里对 match_show 执行了一个循环,利用组件去渲染数据,我们直接全局检索 match_show

通过检索我们找到 match_show 代码js文件,它存在在 _x43826 数组中,在这里看到实例化了一个Vue对象,并且在创建完成后调用了两个方法,第一个是类似是侧边滚动条置顶的操作,第二个是调用了 initData 从英文上来看,这里就类似一个初始化数据的操作 ,我们找到initData 这个方法,直接在方法内下断点

 通过断点分析,我们可以看到这里

 开始就执行了一个Json序列化的过程,而这里序列化产生的数据就是页面渲染出来的数据!

二、解剖数据加密过程

我们拿到了绘制前的关键代码:

let _ = JSON[_x43826[15]]($[_x43826[16]](base64_, STATIC_CONFIG[_x43826[17]]));

我们通过_x43826数组一一对应修改下

 最终修改的代码:

JSON.parse($.rot(base64_, STATIC_CONFIG["KST"])); 

从上图可以看到 base64_ 是实际的数据,STATIC_CONFIG["KST"] 就是一个固定值13,然而在json序列化之前调用了 rot 这个方法,我们断点到这一行代码,然后步入(F11):

可以看到内部调用了两个方法  roottpushmsg ,那我们只需要复刻这两个代码就可以复现他的加密流程了,继续步入(F11)

 这里看到第一个方法的执行代码,进行简单修改,方便我们后期调用

function roott(e, t) { for (var i = "", n = 0; n = 65 && a = 97 && a <= 122 && (o = (a - 97 - 1 * t + 26) % 26 + 97),     i += String.fromCharCode(o) } return i    }

然后我们在 return pushmsg 处下断点,直接执行到下一个断点处(F8),再次步入


 这里我们看到了 pushmsg 的逻辑代码,进行简单修改,方便我们后期调用

function pushmsg(e) { let t = ""; if ("undefined" == typeof window)     try {  t = nodeAtob(e)     } catch (e) {     } else     t = atob(e); const i = t.split("").map(function(e) {     return e.charCodeAt(0) })   , n = new Uint8Array(i)   , a = window.pako.inflate(n); return t = function(e) {     let t, i, n, a, o = "";     const s = e.length;     for (t = 0; t > 4) {  case 0:  case 1:  case 2:  case 3:  case 4:  case 5:  case 6:  case 7:      o += String.fromCharCode(i);      break;  case 12:  case 13:      n = e[t++],      o += String.fromCharCode((31 & i) << 6 | 63 & n);      break;  case 14:      n = e[t++],      a = e[t++],      o += String.fromCharCode((15 & i) << 12 | (63 & n) << 6 | (63 & a) << 0)  }     return o }(new Uint16Array(a)), unescape(t)    }

 在我们把两段代码进行组合调用的时候,会发现报错 pako 未定义,我们去通过百度去查,了解到这东西就是一个 解压 的脚本,他还是一个 开源框架,那我们直接把他的脚本复制到我们的代码中,最后生成的代码为:

/*! pako 2.0.4 https://github.com/nodeca/pako @license (MIT AND Zlib) */!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).pako={})}(this,(function(e){"use strict";var t=(e,t,i,n)=>{let a=65535&e|0,r=e>>>16&65535|0,o=0;for(;0!==i;){o=i>2e3?2e3:i,i-=o;do{a=a+t[n++]|0,r=r+a|0}while(--o);a%=65521,r%=65521}return a|r<{let e,t=[];for(var i=0;i<256;i++){e=i;for(var n=0;n>>1:e>>>1;t[i]=e}return t})());var n=(e,t,n,a)=>{const r=i,o=a+n;e^=-1;for(let i=a;i>>8^r[255&(e^t[i])];return-1^e};var a=function(e,t){let i,n,a,r,o,s,l,d,f,c,h,u,w,b,k,m,_,g,p,v,x,y,E,R;const A=e.state;i=e.next_in,E=e.input,n=i+(e.avail_in-5),a=e.next_out,R=e.output,r=a-(t-e.avail_out),o=a+(e.avail_out-257),s=A.dmax,l=A.wsize,d=A.whave,f=A.wnext,c=A.window,h=A.hold,u=A.bits,w=A.lencode,b=A.distcode,k=(1<<A.lenbits)-1,m=(1<<A.distbits)-1;e:do{u<15&&(h+=E[i++]<<u,u+=8,h+=E[i++]<>>24,h>>>=g,u-=g,g=_>>>16&255,0===g)R[a++]=65535&_;else{if(!(16&g)){if(0==(64&g)){_=w[(65535&_)+(h&(1<<g)-1)];continue t}if(32&g){A.mode=12;break e}e.msg="invalid literal/length code",A.mode=30;break e}p=65535&_,g&=15,g&&(u<g&&(h+=E[i++]<<u,u+=8),p+=h&(1<>>=g,u-=g),u<15&&(h+=E[i++]<<u,u+=8,h+=E[i++]<>>24,h>>>=g,u-=g,g=_>>>16&255,!(16&g)){if(0==(64&g)){_=b[(65535&_)+(h&(1<<g)-1)];continue i}e.msg="invalid distance code",A.mode=30;break e}if(v=65535&_,g&=15,u<g&&(h+=E[i++]<<u,u+=8,u<g&&(h+=E[i++]<<u,u+=8)),v+=h&(1<s){e.msg="invalid distance too far back",A.mode=30;break e}if(h>>>=g,u-=g,g=a-r,v>g){if(g=v-g,g>d&&A.sane){e.msg="invalid distance too far back",A.mode=30;break e}if(x=0,y=c,0===f){if(x+=l-g,g<p){p-=g;do{R[a++]=c[x++]}while(--g);x=a-v,y=R}}else if(f<g){if(x+=l+f-g,g-=f,g<p){p-=g;do{R[a++]=c[x++]}while(--g);if(x=0,f<p){g=f,p-=g;do{R[a++]=c[x++]}while(--g);x=a-v,y=R}}}else if(x+=f-g,g

2;)R[a++]=y[x++],R[a++]=y[x++],R[a++]=y[x++],p-=3;p&&(R[a++]=y[x++],p>1&&(R[a++]=y[x++]))}else{x=a-v;do{R[a++]=R[x++],R[a++]=R[x++],R[a++]=R[x++],p-=3}while(p>2);p&&(R[a++]=R[x++],p>1&&(R[a++]=R[x++]))}break}}break}}while(i<n&&a>3,i-=p,u-=p<<3,h&=(1<<u)-1,e.next_in=i,e.next_out=a,e.avail_in=i<n?n-i+5:5-(i-n),e.avail_out=a{const u=h.bits;let w,b,k,m,_,g,p=0,v=0,x=0,y=0,E=0,R=0,A=0,Z=0,S=0,T=0,O=null,U=0;const D=new Uint16Array(16),I=new Uint16Array(16);let B,N,C,z=null,F=0;for(p=0;p<=r;p++)D[p]=0;for(v=0;v=1&&0===D[y];y--);if(E>y&&(E=y),0===y)return a[f++]=20971520,a[f++]=20971520,h.bits=1,0;for(x=1;x<y&&0===D[x];x++);for(E<x&&(E=x),Z=1,p=1;p<=r;p++)if(Z<<=1,Z-=D[p],Z0&&(0===e||1!==y))return-1;for(I[1]=0,p=1;p<r;p++)I[p+1]=I[p]+D[p];for(v=0;v<n;v++)0!==t[i+v]&&(c[I[t[i+v]]++]=v);if(0===e?(O=z=c,g=19):1===e?(O=o,U-=257,z=s,F-=257,g=256):(O=l,z=d,g=-1),T=0,v=0,p=x,_=f,R=E,A=0,k=-1,S=1<852||2===e&&S>592)return 1;for(;;){B=p-A,c[v]g?(N=z[F+c[v]],C=O[U+c[v]]):(N=96,C=0),w=1<<p-A,b=1<>A)+b]=B<<24|N<<16|C|0}while(0!==b);for(w=1<>=1;if(0!==w?(T&=w-1,T+=w):T=0,v++,0==--D[p]){if(p===y)break;p=t[i+c[v]]}if(p>E&&(T&m)!==k){for(0===A&&(A=E),_+=x,R=p-A,Z=1<<R;R+A<y&&(Z-=D[R+A],!(Z<=0));)R++,Z<<=1;if(S+=1<852||2===e&&S>592)return 1;k=T&m,a[k]=E<<24|R<<16|_-f|0}}return 0!==T&&(a[_+T]=p-A<<24|64<(e>>>24&255)+(e>>>8&65280)+((65280&e)<<8)+((255&e)<{if(!e||!e.state)return _;const t=e.state;return e.total_in=e.total_out=t.total=0,e.msg="",t.wrap&&(e.adler=1&t.wrap),t.mode=1,t.last=0,t.havedict=0,t.dmax=32768,t.head=null,t.hold=0,t.bits=0,t.lencode=t.lendyn=new Int32Array(852),t.distcode=t.distdyn=new Int32Array(592),t.sane=1,t.back=-1,b},S=e=>{if(!e||!e.state)return _;const t=e.state;return t.wsize=0,t.whave=0,t.wnext=0,Z(e)},T=(e,t)=>{let i;if(!e||!e.state)return _;const n=e.state;return t>4),t<48&&(t&=15)),t&&(t15)?_:(null!==n.window&&n.wbits!==t&&(n.window=null),n.wrap=i,n.wbits=t,S(e))},O=(e,t)=>{if(!e)return _;const i=new A;e.state=i,i.window=null;const n=T(e,t);return n!==b&&(e.state=null),n};let U,D,I=!0;const B=e=>{if(I){U=new Int32Array(512),D=new Int32Array(32);let t=0;for(;t<144;)e.lens[t++]=8;for(;t<256;)e.lens[t++]=9;for(;t<280;)e.lens[t++]=7;for(;t<288;)e.lens[t++]=8;for(f(1,e.lens,0,288,U,0,e.work,{bits:9}),t=0;t{let a;const r=e.state;return null===r.window&&(r.wsize=1<=r.wsize?(r.window.set(t.subarray(i-r.wsize,i),0),r.wnext=0,r.whave=r.wsize):(a=r.wsize-r.wnext,a>n&&(a=n),r.window.set(t.subarray(i-n,i-n+a),r.wnext),(n-=a)?(r.window.set(t.subarray(i-n,i),0),r.wnext=n,r.whave=r.wsize):(r.wnext+=a,r.wnext===r.wsize&&(r.wnext=0),r.whaveO(e,15),inflateInit2:O,inflate:(e,i)=>{let r,o,s,l,d,c,A,Z,S,T,O,U,D,I,C,z,F,L,M,H,j,K,P=0;const Y=new Uint8Array(4);let G,X;const W=new Uint8Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]);if(!e||!e.state||!e.output||!e.input&&0!==e.avail_in)return _;r=e.state,r.mode===y&&(r.mode=13),d=e.next_out,s=e.output,A=e.avail_out,l=e.next_in,o=e.input,c=e.avail_in,Z=r.hold,S=r.bits,T=c,O=A,K=b;e:for(;;)switch(r.mode){case 1:if(0===r.wrap){r.mode=13;break}for(;S<16;){if(0===c)break e;c--,Z+=o[l++]<>>8&255,r.check=n(r.check,Y,2,0),Z=0,S=0,r.mode=2;break}if(r.flags=0,r.head&&(r.head.done=!1),!(1&r.wrap)||(((255&Z)<>8))%31){e.msg="incorrect header check",r.mode=E;break}if((15&Z)!==x){e.msg="unknown compression method",r.mode=E;break}if(Z>>>=4,S-=4,j=8+(15&Z),0===r.wbits)r.wbits=j;else if(j>r.wbits){e.msg="invalid window size",r.mode=E;break}r.dmax=1<<r.wbits,e.adler=r.check=1,r.mode=512&Z?10:y,Z=0,S=0;break;case 2:for(;S<16;){if(0===c)break e;c--,Z+=o[l++]<>8&1),512&r.flags&&(Y[0]=255&Z,Y[1]=Z>>>8&255,r.check=n(r.check,Y,2,0)),Z=0,S=0,r.mode=3;case 3:for(;S<32;){if(0===c)break e;c--,Z+=o[l++]<>>8&255,Y[2]=Z>>>16&255,Y[3]=Z>>>24&255,r.check=n(r.check,Y,4,0)),Z=0,S=0,r.mode=4;case 4:for(;S<16;){if(0===c)break e;c--,Z+=o[l++]<>8),512&r.flags&&(Y[0]=255&Z,Y[1]=Z>>>8&255,r.check=n(r.check,Y,2,0)),Z=0,S=0,r.mode=5;case 5:if(1024&r.flags){for(;S<16;){if(0===c)break e;c--,Z+=o[l++]<>>8&255,r.check=n(r.check,Y,2,0)),Z=0,S=0}else r.head&&(r.head.extra=null);r.mode=6;case 6:if(1024&r.flags&&(U=r.length,U>c&&(U=c),U&&(r.head&&(j=r.head.extra_len-r.length,r.head.extra||(r.head.extra=new Uint8Array(r.head.extra_len)),r.head.extra.set(o.subarray(l,l+U),j)),512&r.flags&&(r.check=n(r.check,o,U,l)),c-=U,l+=U,r.length-=U),r.length))break e;r.length=0,r.mode=7;case 7:if(2048&r.flags){if(0===c)break e;U=0;do{j=o[l+U++],r.head&&j&&r.length<65536&&(r.head.name+=String.fromCharCode(j))}while(j&&U<c);if(512&r.flags&&(r.check=n(r.check,o,U,l)),c-=U,l+=U,j)break e}else r.head&&(r.head.name=null);r.length=0,r.mode=8;case 8:if(4096&r.flags){if(0===c)break e;U=0;do{j=o[l+U++],r.head&&j&&r.length<65536&&(r.head.comment+=String.fromCharCode(j))}while(j&&U<c);if(512&r.flags&&(r.check=n(r.check,o,U,l)),c-=U,l+=U,j)break e}else r.head&&(r.head.comment=null);r.mode=9;case 9:if(512&r.flags){for(;S<16;){if(0===c)break e;c--,Z+=o[l++]<>9&1,r.head.done=!0),e.adler=r.check=0,r.mode=y;break;case 10:for(;S<32;){if(0===c)break e;c--,Z+=o[l++]<>>=7&S,S-=7&S,r.mode=27;break}for(;S<3;){if(0===c)break e;c--,Z+=o[l++]<>>=1,S-=1,3&Z){case 0:r.mode=14;break;case 1:if(B(r),r.mode=20,i===w){Z>>>=2,S-=2;break e}break;case 2:r.mode=17;break;case 3:e.msg="invalid block type",r.mode=E}Z>>>=2,S-=2;break;case 14:for(Z>>>=7&S,S-=7&S;S<32;){if(0===c)break e;c--,Z+=o[l++]<>>16^65535)){e.msg="invalid stored block lengths",r.mode=E;break}if(r.length=65535&Z,Z=0,S=0,r.mode=15,i===w)break e;case 15:r.mode=16;case 16:if(U=r.length,U){if(U>c&&(U=c),U>A&&(U=A),0===U)break e;s.set(o.subarray(l,l+U),d),c-=U,l+=U,A-=U,d+=U,r.length-=U;break}r.mode=y;break;case 17:for(;S<14;){if(0===c)break e;c--,Z+=o[l++]<>>=5,S-=5,r.ndist=1+(31&Z),Z>>>=5,S-=5,r.ncode=4+(15&Z),Z>>>=4,S-=4,r.nlen>286||r.ndist>30){e.msg="too many length or distance symbols",r.mode=E;break}r.have=0,r.mode=18;case 18:for(;r.have<r.ncode;){for(;S<3;){if(0===c)break e;c--,Z+=o[l++]<>>=3,S-=3}for(;r.have<19;)r.lens[W[r.have++]]=0;if(r.lencode=r.lendyn,r.lenbits=7,G={bits:r.lenbits},K=f(0,r.lens,0,19,r.lencode,0,r.work,G),r.lenbits=G.bits,K){e.msg="invalid code lengths set",r.mode=E;break}r.have=0,r.mode=19;case 19:for(;r.have<r.nlen+r.ndist;){for(;P=r.lencode[Z&(1<>>24,z=P>>>16&255,F=65535&P,!(C<=S);){if(0===c)break e;c--,Z+=o[l++]<<S,S+=8}if(F>>=C,S-=C,r.lens[r.have++]=F;else{if(16===F){for(X=C+2;S<X;){if(0===c)break e;c--,Z+=o[l++]<>>=C,S-=C,0===r.have){e.msg="invalid bit length repeat",r.mode=E;break}j=r.lens[r.have-1],U=3+(3&Z),Z>>>=2,S-=2}else if(17===F){for(X=C+3;S<X;){if(0===c)break e;c--,Z+=o[l++]<>>=C,S-=C,j=0,U=3+(7&Z),Z>>>=3,S-=3}else{for(X=C+7;S<X;){if(0===c)break e;c--,Z+=o[l++]<>>=C,S-=C,j=0,U=11+(127&Z),Z>>>=7,S-=7}if(r.have+U>r.nlen+r.ndist){e.msg="invalid bit length repeat",r.mode=E;break}for(;U--;)r.lens[r.have++]=j}}if(r.mode===E)break;if(0===r.lens[256]){e.msg="invalid code -- missing end-of-block",r.mode=E;break}if(r.lenbits=9,G={bits:r.lenbits},K=f(1,r.lens,0,r.nlen,r.lencode,0,r.work,G),r.lenbits=G.bits,K){e.msg="invalid literal/lengths set",r.mode=E;break}if(r.distbits=6,r.distcode=r.distdyn,G={bits:r.distbits},K=f(2,r.lens,r.nlen,r.ndist,r.distcode,0,r.work,G),r.distbits=G.bits,K){e.msg="invalid distances set",r.mode=E;break}if(r.mode=20,i===w)break e;case 20:r.mode=21;case 21:if(c>=6&&A>=258){e.next_out=d,e.avail_out=A,e.next_in=l,e.avail_in=c,r.hold=Z,r.bits=S,a(e,O),d=e.next_out,s=e.output,A=e.avail_out,l=e.next_in,o=e.input,c=e.avail_in,Z=r.hold,S=r.bits,r.mode===y&&(r.back=-1);break}for(r.back=0;P=r.lencode[Z&(1<>>24,z=P>>>16&255,F=65535&P,!(C<=S);){if(0===c)break e;c--,Z+=o[l++]<<S,S+=8}if(z&&0==(240&z)){for(L=C,M=z,H=F;P=r.lencode[H+((Z&(1<>L)],C=P>>>24,z=P>>>16&255,F=65535&P,!(L+C<=S);){if(0===c)break e;c--,Z+=o[l++]<>>=L,S-=L,r.back+=L}if(Z>>>=C,S-=C,r.back+=C,r.length=F,0===z){r.mode=26;break}if(32&z){r.back=-1,r.mode=y;break}if(64&z){e.msg="invalid literal/length code",r.mode=E;break}r.extra=15&z,r.mode=22;case 22:if(r.extra){for(X=r.extra;S<X;){if(0===c)break e;c--,Z+=o[l++]<<S,S+=8}r.length+=Z&(1<>>=r.extra,S-=r.extra,r.back+=r.extra}r.was=r.length,r.mode=23;case 23:for(;P=r.distcode[Z&(1<>>24,z=P>>>16&255,F=65535&P,!(C<=S);){if(0===c)break e;c--,Z+=o[l++]<<S,S+=8}if(0==(240&z)){for(L=C,M=z,H=F;P=r.distcode[H+((Z&(1<>L)],C=P>>>24,z=P>>>16&255,F=65535&P,!(L+C<=S);){if(0===c)break e;c--,Z+=o[l++]<>>=L,S-=L,r.back+=L}if(Z>>>=C,S-=C,r.back+=C,64&z){e.msg="invalid distance code",r.mode=E;break}r.offset=F,r.extra=15&z,r.mode=24;case 24:if(r.extra){for(X=r.extra;S<X;){if(0===c)break e;c--,Z+=o[l++]<<S,S+=8}r.offset+=Z&(1<>>=r.extra,S-=r.extra,r.back+=r.extra}if(r.offset>r.dmax){e.msg="invalid distance too far back",r.mode=E;break}r.mode=25;case 25:if(0===A)break e;if(U=O-A,r.offset>U){if(U=r.offset-U,U>r.whave&&r.sane){e.msg="invalid distance too far back",r.mode=E;break}U>r.wnext?(U-=r.wnext,D=r.wsize-U):D=r.wnext-U,U>r.length&&(U=r.length),I=r.window}else I=s,D=d-r.offset,U=r.length;U>A&&(U=A),A-=U,r.length-=U;do{s[d++]=I[D++]}while(--U);0===r.length&&(r.mode=21);break;case 26:if(0===A)break e;s[d++]=r.length,A--,r.mode=21;break;case 27:if(r.wrap){for(;S<32;){if(0===c)break e;c--,Z|=o[l++]<<S,S+=8}if(O-=A,e.total_out+=O,r.total+=O,O&&(e.adler=r.check=r.flags?n(r.check,s,O,d-O):t(r.check,s,O,d-O)),O=A,(r.flags?Z:R(Z))!==r.check){e.msg="incorrect data check",r.mode=E;break}Z=0,S=0}r.mode=28;case 28:if(r.wrap&&r.flags){for(;S<32;){if(0===c)break e;c--,Z+=o[l++]<<S,S+=8}if(Z!==(4294967295&r.total)){e.msg="incorrect length check",r.mode=E;break}Z=0,S=0}r.mode=29;case 29:K=k;break e;case E:K=g;break e;case 31:return p;case 32:default:return _}return e.next_out=d,e.avail_out=A,e.next_in=l,e.avail_in=c,r.hold=Z,r.bits=S,(r.wsize||O!==e.avail_out&&r.mode<E&&(r.mode{if(!e||!e.state)return _;let t=e.state;return t.window&&(t.window=null),e.state=null,b},inflateGetHeader:(e,t)=>{if(!e||!e.state)return _;const i=e.state;return 0==(2&i.wrap)?_:(i.head=t,t.done=!1,b)},inflateSetDictionary:(e,i)=>{const n=i.length;let a,r,o;return e&&e.state?(a=e.state,0!==a.wrap&&11!==a.mode?_:11===a.mode&&(r=1,r=t(r,i,n,0),r!==a.check)?g:(o=N(e,i,n,n),o?(a.mode=31,p):(a.havedict=1,b))):_},inflateInfo:"pako inflate (from Nodeca project)"};const z=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var F=function(e){const t=Array.prototype.slice.call(arguments,1);for(;t.length;){const i=t.shift();if(i){if("object"!=typeof i)throw new TypeError(i+"must be non-object");for(const t in i)z(i,t)&&(e[t]=i[t])}}return e},L=e=>{let t=0;for(let i=0,n=e.length;i<n;i++)t+=e[i].length;const i=new Uint8Array(t);for(let t=0,n=0,a=e.length;t<a;t++){let a=e[t];i.set(a,n),n+=a.length}return i};let M=!0;try{String.fromCharCode.apply(null,new Uint8Array(1))}catch(e){M=!1}const H=new Uint8Array(256);for(let e=0;e=252?6:e>=248?5:e>=240?4:e>=224?3:e>=192?2:1;H[254]=H[254]=1;var j=e=>{if("function"==typeof TextEncoder&&TextEncoder.prototype.encode)return(new TextEncoder).encode(e);let t,i,n,a,r,o=e.length,s=0;for(a=0;a<o;a++)i=e.charCodeAt(a),55296==(64512&i)&&a+1<o&&(n=e.charCodeAt(a+1),56320==(64512&n)&&(i=65536+(i-55296<<10)+(n-56320),a++)),s+=i<128?1:i<2048?2:i<65536?3:4;for(t=new Uint8Array(s),r=0,a=0;r<s;a++)i=e.charCodeAt(a),55296==(64512&i)&&a+1<o&&(n=e.charCodeAt(a+1),56320==(64512&n)&&(i=65536+(i-55296<<10)+(n-56320),a++)),i<128?t[r++]=i:i>>6,t[r++]=128|63&i):i>>12,t[r++]=128|i>>>6&63,t[r++]=128|63&i):(t[r++]=240|i>>>18,t[r++]=128|i>>>12&63,t[r++]=128|i>>>6&63,t[r++]=128|63&i);return t},K=(e,t)=>{const i=t||e.length;if("function"==typeof TextDecoder&&TextDecoder.prototype.decode)return(new TextDecoder).decode(e.subarray(0,t));let n,a;const r=new Array(2*i);for(a=0,n=0;n<i;){let t=e[n++];if(t4)r[a++]=65533,n+=o-1;else{for(t&=2===o?31:3===o?15:7;o>1&&n<i;)t=t<1?r[a++]=65533:t>10&1023,r[a++]=56320|1023&t)}}return((e,t)=>{if(t<65534&&e.subarray&&M)return String.fromCharCode.apply(null,e.length===t?e:e.subarray(0,t));let i="";for(let n=0;n{(t=t||e.length)>e.length&&(t=e.length);let i=t-1;for(;i>=0&&128==(192&e[i]);)i--;return it?i:t},Y={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"};var G=function(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0};var X=function(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1};const W=Object.prototype.toString,{Z_NO_FLUSH:q,Z_FINISH:J,Z_OK:Q,Z_STREAM_END:V,Z_NEED_DICT:$,Z_STREAM_ERROR:ee,Z_DATA_ERROR:te,Z_MEM_ERROR:ie}=c;function ne(e){this.options=F({chunkSize:65536,windowBits:15,to:""},e||{});const t=this.options;t.raw&&t.windowBits>=0&&t.windowBits=0&&t.windowBits15&&t.windowBits0&&r===V&&i.state.wrap>0&&0!==e[i.next_in];)C.inflateReset(i),r=C.inflate(i,o);switch(r){case ee:case te:case $:case ie:return this.onEnd(r),this.ended=!0,!1}if(s=i.avail_out,i.next_out&&(0===i.avail_out||r===V))if("string"===this.options.to){let e=P(i.output,i.next_out),t=i.next_out-e,a=K(i.output,e);i.next_out=t,i.avail_out=n-t,t&&i.output.set(i.output.subarray(e,e+t),0),this.onData(a)}else this.onData(i.output.length===i.next_out?i.output:i.output.subarray(0,i.next_out));if(r!==Q||0!==s){if(r===V)return r=C.inflateEnd(this.strm),this.onEnd(r),this.ended=!0,!0;if(0===i.avail_in)break}}return!0},ne.prototype.onData=function(e){this.chunks.push(e)},ne.prototype.onEnd=function(e){e===Q&&("string"===this.options.to?this.result=this.chunks.join(""):this.result=L(this.chunks)),this.chunks=[],this.err=e,this.msg=this.strm.msg};var re=ne,oe=ae,se=function(e,t){return(t=t||{}).raw=!0,ae(e,t)},le=ae,de=c,fe={Inflate:re,inflate:oe,inflateRaw:se,ungzip:le,constants:de};e.Inflate=re,e.constants=de,e.default=fe,e.inflate=oe,e.inflateRaw=se,e.ungzip=le,Object.defineProperty(e,"__esModule",{value:!0})}));function roott(e, t) { for (var i = "", n = 0; n = 65 && a = 97 && a <= 122 && (o = (a - 97 - 1 * t + 26) % 26 + 97), i += String.fromCharCode(o) } return i }function pushmsg(e) { let t = ""; if ("undefined" == typeof window) try { t = nodeAtob(e) } catch (e) { } else t = atob(e); const i = t.split("").map(function(e) { return e.charCodeAt(0) }) , n = new Uint8Array(i) , a = window.pako.inflate(n); return t = function(e) { let t, i, n, a, o = ""; const s = e.length; for (t = 0; t > 4) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: o += String.fromCharCode(i); break; case 12: case 13: n = e[t++], o += String.fromCharCode((31 & i) << 6 | 63 & n); break; case 14: n = e[t++], a = e[t++], o += String.fromCharCode((15 & i) << 12 | (63 & n) << 6 | (63 & a) << 0) } return o }(new Uint16Array(a)), unescape(t) }function main(e){ var i=pushmsg(roott(e, 13));return JSON.parse(i);}

我们通过调用main方法,传入解密前的base64数据即可获得比赛相关的 json 数据 ,那这段加密前的json从哪里来的呢,我们直接全局检索(Ctrl+Shift+F )这段base64数据的一段代码

这里检索到base64数据位置,点击进入 ,他来自wc_xxxx.js文件中,那这个文件又是在什么地方进行加载呢,直接全局检索(Ctrl+Shift+F )这个js的名字

 我们可以看到这个base64的代码就在页面中进行加载,那我们直接可以直接通过正则匹配,拿到这段base64数据进行解密就可以了!

 三、通过 C# WinForm 进行获取调用

这里我们把js运行在 CefSharp 中,接下来vs中新建一个WinForm应用程序

1.第一步获取页面数据,抓取base64数据所在js地址,通过正则去匹配获取到地址

  string GetPageData() {     var html = HttpHelper.httpGet(_baseUrl);     string pattern = "";     var base64 = "";     if (Regex.IsMatch(html, pattern))     {  var jsUrl = Regex.Match(html, pattern).Groups[1].Value;  base64 = GetJsBase64Data(jsUrl);     }     return base64; }

 //2.获取js文件中base64数据

  public class ForceHttp2Handler : DelegatingHandler {     public ForceHttp2Handler(HttpMessageHandler innerHandler)  : base(innerHandler)     {     }     protected override Task SendAsync(  HttpRequestMessage request, CancellationToken cancellationToken)     {  request.Version = new Version(2, 0);  return base.SendAsync(request, cancellationToken);     } } //2.获取js文件中base64数据 string GetJsBase64Data(string url) {     var html = "";     using (var client = new HttpClient(new ForceHttp2Handler(new WinHttpHandler())))     {  var message = new HttpRequestMessage(HttpMethod.Get, url + "?t=" + DateTime.Now.Ticks);  message.Headers.Add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36");  message.Headers.Add("pragma", "no-cache");  message.Headers.Add("cache-control", "no-cache");  message.Headers.Add("accept", "*/*");  message.Headers.Add("referer", "https://live.leisu.com/wanchang");  message.Headers.Add("accept-language", "zh-CN,zh;q=0.9");  message.Headers.Add("cookie", "UM_distinctid=17ef839bc3d7b-041bfbe9cf3771-576153e-1fa400-17ef839bc3e7b2");  message.Headers.Add("cookie", "Hm_lvt_63b82ac6d9948bad5e14b1398610939a=1644842041");  message.Headers.Add("cookie", "Hm_lpvt_63b82ac6d9948bad5e14b1398610939a=1644843313");  var response = client.SendAsync(message).Result;  if (response.IsSuccessStatusCode)  {      html = response.Content.ReadAsStringAsync().Result;  }     }     string pattern = "window\\[.*?\\] ='(.*?)';";     var base64 = "";     if (Regex.IsMatch(html, pattern))     {  base64 = Regex.Match(html, pattern).Groups[1].Value;     }     return base64; }

3.第三步将得到的base64数据进行解密输出

    var base64 = GetPageData();     //拼接调用函数     var main = $"main('{base64}')";     //加载解析js文件     var jsStr = File.ReadAllText(AppDomain.CurrentDomain.BaseDirectory + "Scripts/ls.js");     //调用js拼接     jsStr = jsStr.Replace("#Code#", "return " + main);     //执行js返回结果     var rel = await chromeBrowser.GetBrowser().MainFrame.EvaluateScriptAsync(jsStr, null);

 4.最后我们就得到了解密出的数据

 最后附上懒人资源地址:C#Winform雷速网站逆向分析

 续集:C#WinForm实现雷速网站比赛MQTT逆向采集_qq942564942的博客-CSDN博客

总结

以上就是C#实现雷速网站逆向的全部过程,不断学习,终能达到彼岸。