没想到SCU拿美国卡耐基梅隆大学的平时作业当咱的期末考项目,考完了以后上传一个writeup供大家参考。当时两个安全项目和游戏项目可是把戴安娜折腾惨了,第一次感受到了大学期末周的问候。好了话不多说,上题解!
题面:
项目名称 | Lab1-Decode | ||||||||||||||||||||||||||||||||
项目环境 | 表1 项目开发环境
| ||||||||||||||||||||||||||||||||
项目过程和结果的描述 | 2023年12月31日&1月1日 下面展示思路:
2.16进制转字符串 图1:Intel是小端序列,因此自己在DEV里面写了一个decode代码 图2:得到以下信息: 3.对得到的密文进行解密: 图4:研究extract_message1(int start, int stride)函数可知,它传入一个start和stride,将data数组转换成字符串 extract_message1这个函数的功能是,从 data 数组的首地址偏移 start + 1 地址开始,每转换 stride -1 个字符后,就跳过一个字符不转换,重复执行这样的操作直到转换到最后一个字符. 已知明文最开始为:From: 可利用其来倒推出start=09和stride=03。解读代码可知Start09是dummy的int型4字节里面最低的8位,stride03是次低的8位。
由process_keys12函数可知,令地址key1偏移*key1为dummy来定位dummy,*key2来为dummy赋值。 注意:因此打断点打在主函数,extract1函数里面的int*key1是局部变量,不存在于主函数里面。So,取地址是取&key1而非key1。 5.调试看key1和dummy的地址:并计算偏移量 derta=9*16-3*16=-96, 易知:*key1=-96/4=-24.即令*key1=24可使dummy地址=key1。再令*key2=777,使得dummy为0x00000309,成功使start为9,stride为3。 总结:*key1=-24;*key2=777. 6.输入到程序里面: 显示正确,并得到关于key3,4提示:要选择key3key4来调用extract2并且避免调用extract1。
图8 main函数 易知,只有当*msg1==‘\0’时,才会输出msg2 所以我们现在想怎么让*msg1==‘\0’。
由题, extract1函数 cccccccccabcdefghijk从第10个字符开始读 Bc ef hi
Extract2函数 cccccccccabcdefghijk从第9个字符开始读 A d g j 若让第10个字符==‘\0’就可以在不影响extract2函数输出结果的情况下得到msg2. 由ASCII码和十六进制编译准则,如图 目标即修改data【2】为0x72004663;
接下来我们又看到了key3key4; void process_keys34(int* key3, int* key4) { *(((int*)&key3) + *key3) += *key4; //key4为△derta. } 于是仿造dummy被key1移动地址来定位,*key2来赋值的做法。 我们用&key3偏移*key3的量对data【2】定位。将*key4用来对data【2】改值,这里72004663-72464663=-4587520,key4传入-4587520即可。 调试监视查看&key3和&data【2】:
△=*key3 上网计算可知:*key3=-5367456920/4=1341864230 综上, *key1=-24, *key2=777. *key3=5367456920/4=1341864230 *key4=-4587520 在属性-->调试-->命令参数里面输入: -24 777 1341864230 -4587520 显示正确,下班! (开心) 源码: #include <stdio.h> int prologue [] = { int data [] = { int epilogue [] = { char message[100]; void usage_and_exit(char * program_name) { void process_keys12 (int * key1, int * key2) { void process_keys34 (int * key3, int * key4) { *(((int *)&key3) + *key3) += *key4; char * extract_message1(int start, int stride) { for (i = 0, j = start + 1; ! done; j++) { if (*(((char *) data) + j) == '\0') {
for (i = 0, j = start; int main (int argc, char *argv[]) key3 = key4 = 0; process_keys12(&key1, &key2); start = (int)(*(((char *) &dummy))); if (key3 != 0 && key4 != 0) { msg1 = extract_message1(start, stride); if (*msg1 == '\0') {//*msg1 == '\0' return 0; |