逆向工程实验Lab3 | 您所在的位置:网站首页 › 定义的英语翻译 › 逆向工程实验Lab3 |
赞赏码 & 联系方式 & 个人闲话
逆向工程前言
Lab3
1、阅读:https://blog.csdn.net/cnhk1225/article/details/53568996然后回答问题:What does this code do?
代码注释: MSIL代码的注释如下(Java代码大同小异,功能也相同,此处就不加以注释): Optimizing csc .NET compiler from MSVS 2015 (/o switch), ildasm output: .method public hidebysig static bool f(char a) cil managed { // Code size 26 (0x1a) //代码大小 26 (0x1a) .maxstack 8 //计算堆栈能存8个值 IL_0000: ldarg.0 //将this指针压入栈 IL_0001: ldc.i4.s 97 //97放到计算堆栈上 IL_0003: blt.s IL_000c //如果第一个值小于第二个值则将控制转移到目标指令 IL_0005: ldarg.0 //将this指针压入栈 IL_0006: ldc.i4.s 122 //122放到计算堆栈上 IL_0008: bgt.s IL_000c //如果第一个值大于第二个值则将控制转移到目标指令 IL_000a: ldc.i4.1 //把1放到计算堆栈上 IL_000b: ret //return 1 IL_000c: ldarg.0 //将this指针压入栈 IL_000d: ldc.i4.s 65 //65放到计算堆栈上 IL_000f: blt.s IL_0018 //如果第一个值小于第二个值则将控制转移到目标指令 IL_0011: ldarg.0 //将this指针压入栈 IL_0012: ldc.i4.s 90 //90放到计算堆栈上 IL_0014: bgt.s IL_0018 //如果第一个值大于第二个值则将控制转移到目标指令 IL_0016: ldc.i4.1 //把1放到计算堆栈上 IL_0017: ret //return 1 IL_0018: ldc.i4.0 //把0放到计算堆栈上 IL_0019: ret //return 0 } // end of method some_class::f 小结与讨论: 代码段的含义是:判断一个字符是否为字母。如果是字母(大小写形式不论)则返回1;其他字符则返回0。 2、2017bath这张图片有一些文字片段可能简单加密了,是某人说的,此人的姓名是什么?(hint:hex editor) Step1:通过十六进制编辑器打开2017bath.jpg 可以找到Rail-Fence的字符串,表明可能使用了栅栏密码进行加密。 Step2:将jpg后缀改为zip,解压缩后得到txt文本 文本内容如下: CrudreasrsheheanaulhfouCmhlaopiaeifltouermrtdpiyeCntpmafhnpbgmbaoagspeuteuwtecwokpetwutileolctnreoicottievhetepriogoseIretodaiithgottfeorhersnueualtebtfamtnseetehrnieipooilrshashyhsrmttmanariaictntgutdeeonmotaudeowuselctnfeoghrtsbaCrgarhtbprthcirarQktodbeatees Step3:破解栅栏密码 加密方式是栅栏密码,栅栏数是不确定的,所以进行暴力破解。 代码如下: #include #include int main() { char cipher[] = "CrudreasrsheheanaulhfouCmhlaopiaeifltouermrtdpiyeCntpmafhnpbgmbaoagspeuteuwtecwokpetwutileolctnreoicottievhetepriogoseIretodaiithgottfeorhersnueualtebtfamtnseetehrnieipooilrshashyhsrmttmanariaictntgutdeeonmotaudeowuselctnfeoghrtsbaCrgarhtbprthcirarQktodbeatees"; int len = strlen(cipher); int i; char temp[50][50]; int j, k; int row, line; int part; int num; for (i = 2; i < 11; i++) { printf("每组字数%d\n", i); row = i; line = ceil(len / double(i)); part = len % i; num = 0; for (j = 0; j < part; j++) { for (k = 0; k < line; k++) { temp[j][k] = cipher[num]; num++; } } for (; j < row; j++) { for (k=0; k < line-1; k++) { if (num > len) break; temp[j][k] = cipher[num]; num++; } } num = 0; for (k = 0; k < line; k++) { for (j = 0; j < row; j++) { if (num > len) break; printf("%c", temp[j][k]); num++; } } printf("\n\n"); } }运行结果如下: 当每字符数为9时,解密的结果最符合逻辑。所以明文为:CppisahorriblelanguageItsmademorehorriblebythefactthatalotofsubstandardprogrammersuseittothepointwhereitsmuchmucheasiertogeneratetotalanduttercrapwithitQuitefranklyevenifthechoiceofCweretodonothingbutkeeptheCppprogrammersoutthatinitselfwouldbeahugereasontouseC Step4:确定问题答案 断一波句: Cpp is a horrible language Its made more horrible by the fact that a lot of substandard programmers use it to the point where its much much easier to generate total and utter crap with it Quite frankly even if the choice of C were to do nothing but keep the Cpp programmers out that in itself would be a huge reason to use C 这是Linux之父Linus Torvalds说的,故问题的答案为:Linus Torvalds。 3、运行CrackMe1.exe,提示 "嗯,对了" 代表成功。首先修改exe使得出现成功提示,其次不修改exe输入正确的密码达到成功的目的。(hint:https://blog.csdn.net/Nagi_Way/article/details/68961121) Ⅰ:修改exe使得出现成功提示Step1:分析Crack Me按钮源代码 思路:分析代码可知,只要把==改为!=就ok了~ Step2:通过IDA查看CrackMe1.exe文件 找到了判断语句,就是这个brtrue.s。查阅资料可知,brtrue.S表示如果value为true、非空或非零,则将控制转移到目标指令(短格式)。而brfalse.S则恰恰相反,如果value为 false、空引用或零,则将控制转移到目标指令。所以,我们只要把此处改为brfalse.s就可以了。 Step3:通过十六进制编辑器修改 通过ida找出两条判断语句的十六进制表示分别是2D 0F、2C 0B。因为0F、0B实际上是跳转地址,所以只需将2D改为2C(即将brtrue.S改为brfalse.s)。 Step4:验证修改结果 随便输如一个字符串,就可以看到成功的显示: Step1:分析Crack Me按钮源代码 用.NET Reflector软件解析CrackMe1.exe,在button1_Click函数中里能看到: 打开Encode加密函数,可以发现是3DES加密: Step2:3DES在线解密 我们找到一个在线解密3DES网站(http://tool.chacuo.net/crypt3des)可以进行解密。加密模式选择CBC,填充选择pkcs5padding, 密钥为wctf{wol,偏移量为dy_crack},输出使用base64加密。 确定算法参数后,便可成功解密。这里的参数选择其实也是枚举试出来的。 Step3:验证解密结果 在CrackMe1.exe中输入wctf{dotnet_crackme1},即可出现成功提示: Step1:修改CrackMe1.exe验证密码出现成功提示 通过十六进制编辑器将密码判断处的字符串修改为E41614018,3DES加密结果为“Kisgmrp27z0I0OANbRfC2A==”。 验证修改后的密码E41614018: Step2:修改字符串为自定义 字符串“大家好!我是”修改为“AAAAAA”: 字符串“@无所不能的魂大人”修改为“BBBBBBBBB”: 微博链接“Sina Visitor System”修改为学校官网链接“安徽大学”: 字符串“编点练习题太TMD难了。。欢迎投稿哦!投稿地址[email protected]”修改为“E41614018 E41614003 E41614007 Hello,World”: Step3:查看修改后的最终效果 点击BBBBBBBBB处的链接,打开学校官网网页: Step1:分析login.exe验证登陆密码的源码 用.NET Reflector这个软件解析login.exe,找出与出现成功提示相关的源码: 分析代码可以知道:当输入的字符长度为9,所有字符的ASCII码算术运算加后是0x1d8,逻辑运算与后是0x42的时候,系统就会输出"You Get It!"。 Step2:确定login.exe的登陆密码 满足条件的字符串有很多,老师的提示是上一届同学的学号,那么就可以确定“E415140”这7位,所以只要暴力破解后两位即可。 代码如下: #include #include int main() { char c[] = "0123456789Ee"; int len = strlen(c); char a[9]; int i1, i2, i3, i4, i5, i6, i7, i8, i9; int num = 0, num2 = 0; int j; int flag = 0; for (i1 = 0; i1 < 1; i1++) { //if (flag == 1) //break; //a[0] = c[i1]; a[0] = 'E'; for (i2 = 0; i2 < 1; i2++) { //if (flag == 1) //break; //a[1] = c[i2]; a[1] = '4'; for (i3 = 0; i3 < 1; i3++) { //if (flag == 1) //break; //a[2] = c[i3]; a[2] = '1'; for (i4 = 0; i4 < 1; i4++) { //if (flag == 1) //break; //a[3] = c[i4]; a[3] = '5'; for (i5 = 0; i5 < 1; i5++) { //if (flag == 1) //break; //a[4] = c[i5]; a[4] = '1'; for (i6 = 0; i6 < 1; i6++) { //if (flag == 1) //break; //a[5] = c[i6]; a[5] = '4'; for (i7 = 0; i7 < 1; i7++) { //if (flag == 1) //break; //a[6] = c[i7]; a[6] = '0'; for (i8 = 0; i8 < len; i8++) { //if (flag == 1) //break; a[7] = c[i8]; for (i9 = 0; i9 < len; i9++) { //if (flag == 1) //break; a[8] = c[i9]; for (j = 0; j < 9; j++) { num = num + (int)a[j]; num2 ^= (int)a[j]; } if (num == 472 && num2 == 66) { for (j = 0; j < 9; j++) printf("%c", a[j]); flag = 1; printf("\n"); } num = 0; num2 = 0; } } } } } } } } } }运行结果如下: Step3:验证login.exe的登陆密码 将这两个学号任意一个输入到login.exe,即可成功: Step4:确定程序员信息 查询这两个学号,可找到: 这两位就是我们想找的设计这个程序的人。 ps: 这道题是两位学长学姐出的,在此感谢学长学姐们的付出。听说出题的原因好像是保研后闲着没有什么事情做(更新:学长在评论区表示是老师让写的哈哈哈)。不清楚睿敏和飞哥有没有继承这个传统啊 : ) |
CopyRight 2018-2019 实验室设备网 版权所有 |