学破解第124天,《攻防世界web新手练习区simple_js》学习
前言:
从小学到大专(计算机网络技术专业),玩过去的,所以学习成绩惨不忍睹,什么证书也没考,直到找不到工作才后悔,不知道怎么办才好。
2017年12月16日,通过19元注册码注册论坛账号,开始做伸手党,潜水一年多,上来就是找软件。(拿论坛高大上的软件出去装X)
2018年8月某一天,报名了华中科技大学网络教育本科(计算机科学与技术专业)2018级秋季。(开始提升学历)
2019年6月17日,不愿再做小菜鸟一枚,开始零基础学习破解。(感谢小糊涂虫大哥在我刚开始学习脱壳时,录制视频解答我的问题)
2020年7月7日,感谢H大对我的鼓励,拥有了第一篇获得优秀的文章。(接下来希望学习逆向,逆天改命)
坛友们,年轻就是资本,和我一起逆天改命吧,我的学习过程全部记录及学习资源:https://www.52pojie.cn/thread-1208234-1-1.html
立帖为证!--------记录学习的点点滴滴
0x1行为分析
1.选择这道练习题,生成在线场景,访问这个地址:
2.据上图可知,这是一个对话框(我不知道这叫啥,瞎说的),有一个提示信息,有一个文本框,有一个确定和输入按钮,看浏览器当前页面一直在转圈,感觉像是和OD下断点让程序中断了一样。
3.随便输入123456试试,看到提示:FAUX PASSWORD HAHA,应该是错误提示信息,再换一个654321试试,发现还是提示FAUX PASSWORD HAHA,说明密码错误会固定弹出这个提示,与flag没有关系,不是动态生成的。
0x2查看源代码
1.我发现web程序的代码与c语言代码不一样,这个html代码电脑上F12都能看到,exe程序很难还原,只能IDA F5看伪代码或者动态调试。
2.这里直接F12查看源代码,我看到了一段类似C语言代码的东西:
function dechiffre(pass_enc){
var pass = "70,65,85,88,32,80,65,83,83,87,79,82,68,32,72,65,72,65";
var tab = pass_enc.split(',');
var tab2 = pass.split(',');var i,j,k,l=0,m,n,o,p = "";i = 0;j = tab.length;
k = j + (l) + (n=0);
n = tab2.length;
for(i = (o=0); i < (k = j = n); i++ ){o = tab[i-l];p += String.fromCharCode((o = tab2[i]));
if(i == 5)break;}
for(i = (o=0); i < (k = j = n); i++ ){
o = tab[i-l];
if(i > 5 && i < k-1)
p += String.fromCharCode((o = tab2[i]));
}
p += String.fromCharCode(tab2[17]);
pass = p;return pass;
}
String["fromCharCode"](dechiffre("\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30"));
h = window.prompt('Enter password');
alert( dechiffre(h) );
3.看起来很复杂,把它当成c语言看,凭借简单的C语言基础也能解开这道题,这只是一道新手练习题,没接触前端,用这种方式去学习也不错,前面都是题外话了,接下来看function,这个类似c语言中定义函数,所以这段代码我可以这样来看,前面定义了一个函数,后面去调用它,如果输入的密码正确,函数会输出正确的flag。
4.dechiffre这个函数有一个参数,所以分析的时候,先看调用处,(dechiffre("\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30"),用c语言printf函数打印一下:55,56,54,79,115,69,114,116,107,49,50。
5.进去之后发现定义了一个pass,也是一串数字组成,接着看到了这句pass_enc.split(',');这应该是结构体调用内部的函数,又不太像,有点像c++里面的类的成员函数的调用,百度一下split,原来这是一个以逗号分隔这一串是数字的函数,那么tab就像是一个数组接收了这一串返回的数字,不过没明白这里面定义数组为什么没用中括号,tab2就是将pass分隔存储的整形数组,接下来好像是定义一串变量,这个var也太强了,怎么区分int,char,double这些类型的???先不去管它,毕竟我也不是学前端的,然后看到j = tab.lengt,猜也能猜到j是长度,不过这个length怎么没小括号,难道定义的变量属性自带长度?可能是隐藏了函数的实现细节吧。
6.突然发现,后面两个for循环等着我,还有一个不知道干啥的fromCharCode函数,这样手动调试不是个办法,而且在运算中还插入的赋值操作k = j + (l) + (n=0);这个我去c语言里面调试一下。
int i = 2, j = 4, k = 6;
i = i + j + (k = 3);
printf("k=%d\n",k);
printf("i + j + (k = 0)=%d\n", i);
观输出结果,发现上面的代码等价于
int i = 2, j = 4, k = 6;
k = 3;
i = i + j + k;
printf("k=%d\n",k);
printf("i + j + (k = 0)=%d\n", i);
这个代码运算逻辑问题解决了,可是这段js代码还是要命,怎么分析它呢?
7.先从其它的地方寻找突破口吧,百度了一下fromCharCode() 函数可接受一个指定的 Unicode 值,然后返回一个字符串。一下子分析不出,那我就只看函数的输入输出,pass最终的值由p决定,pass_enc这个值完全没有处理,我在思考思考,两个常量值是固定的,而加密函数确定,那么输出的值肯定也是确定的。此时,我有一种这个函数并不是加密产生的flag的,很可能它什么都没有做!
0x3换思路
1.前端程序,不会调试啊,吾爱的大杀器OD和IDA都派不上用场,这些代码我也没本事变成C语言形式的代码,那么这种前端程序能不能直接修改呢?
2.通过百度得知了console.log()函数类似于c语言的printf函数,可以用来打印变量的值,但是又没编辑器,通过百度发现F12打开源代码视图,点击行号,一样可以对程序下断点调试,那么我直接对函数最后一行下断点,发现p的值是"FAUX PASSWORD HAHA",此时的想法得到了印证,不管我输入什么,最终都一定提示这个,因为传入的参数pass_enc经过这个函数不会改变。
3.说明pass_enc很可能就是密码,将它转换成ascii输出,以下为C语言代码:
int main(int argc, char **argv)
{
int arr[] = { 55,56,54,79,115,69,114,116,107,49,50,0 };
for (int m = 0; arr[m]; m++)
{
printf("%c", arr[m]);
}
system("pause");
}
输出结果:786OsErtk12
4.看题目,Flag格式为 Cyberpeace{xxxxxxxxx},所以最终的格式为Cyberpeace{786OsErtk12}。
附上成功截图:
0x4总结
1.最终查阅了相关资料,这个程序是先执行了window.prompt('Enter password');这句代码,给了一个提示框,返回值h接收的是我输入的内容。
2.alert是一个错误警告框,后面弹的固定字符串FAUX PASSWORD HAHA就是它的作用。
3.通过前面两条总结其实可以发现这个程序真的是新手练习,只要能看懂提示框,就会发现我输入的内容h完全没处理,也不用去看那个函数,直接就能得到flag。
4.听大佬们说学逆向先学正向,这回我算是感觉到了,凭借c语言经验分析一下exe程序还行,要是用c语言经验分析web程序,像这种特别简单都能要我半条命。
PS:善于总结,善于发现,找到分析问题的思路和解决问题的办法。虽然我现在还是零基础的小菜鸟一枚,也许学习逆向逆天改命我会失败,但也有着成功的可能,只要还有希望,就决不放弃!