SCU【C】程序设计基础期末安全项目lab1-Decode-writeup(附题目&源码)

没想到SCU拿美国卡耐基梅隆大学的平时作业当咱的期末考项目,考完了以后上传一个writeup供大家参考。当时两个安全项目和游戏项目可是把戴安娜折腾惨了,第一次感受到了大学期末周的问候。好了话不多说,上题解!

题面:

项目名称

Lab1-Decode

项目环境 

表1 项目开发环境

硬件环境

CPU

Intel Core i5-1135G7,2.4 GHZ

内存

8G

操作系统

Windows

10,Professional版本

开发IDE

VisualStudio

2022版本

项目过程和结果的描述

2023年12月31日&1月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位。

  1. 自学数制知识。由3可知,dummy应该等于=0x....0309=777

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

  1. 观察extract2函数:从 data 数组的首地址偏移 start 地址开始,每读入一个字符,就跳过stride-1个字符,直到转换到最后一个字符
  1. 由7可知start=9,stride=3,不用修改start和stride的值。
  2. 下面研究main函数:

图8 main函数

易知,只有当*msg1==‘\0’时,才会输出msg2

所以我们现在想怎么让*msg1==‘\0’。

  1. 让*msg1==‘\0’:

由题,

extract1函数 cccccccccabcdefghijk从第10个字符开始读

Bc ef hi

                         

             

Extract2函数 cccccccccabcdefghijk从第9个字符开始读

                      A  d  g  j

若让第10个字符==‘\0’就可以在不影响extract2函数输出结果的情况下得到msg2.

由ASCII码和十六进制编译准则,如图

目标即修改data【2】为0x72004663;

  1. 如何修改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】:

名称

类型

&dummy

0x000000852751f7a4 {1}

int *

名称

类型

&key1

0x000000852751f804 {-858993460}

int *

名称

类型

&key3(断点打extract34里面)

注意这个&key3☞外部函数里的&key3

0x000000000014fbf0 {0x000000000014fcb4 {2147483647}}

int * *

名称

类型

&data[2]

Project1.exe!0x000000014001e088 {1919174243}

int *

△=*key3

上网计算可知:*key3=-5367456920/4=1341864230

综上,

*key1=-24,

*key2=777.

*key3=5367456920/4=1341864230

*key4=-4587520

在属性-->调试-->命令参数里面输入:

-24 777 1341864230 -4587520

显示正确,下班!  (开心)

源码:

#include <stdio.h>
#include <stdlib.h>

int prologue [] = {
    0x5920453A, 0x54756F0A, 0x6F6F470A, 0x21643A6F,
    0x6E617920, 0x680A6474, 0x6F697661, 0x20646E69,
    0x63636363, 0x63636363, 0x72464663, 0x6F6D6F72,
    0x63636363, 0x63636363, 0x72464663, 0x6F6D6F72,
    0x2C336573, 0x7420346E, 0x20216F74, 0x726F5966,
    0x7565636F, 0x20206120, 0x6C616763, 0x74206C6F,
    0x20206F74, 0x74786565, 0x65617276, 0x32727463,
    0x594E2020, 0x206F776F, 0x79727574, 0x4563200A
};

int data [] = {
        0x63636363, 0x63636363, 0x72464663, 0x6F6D6F72,
          0x466D203A, 0x65693A72, 0x43646E20, 0x6F54540A,
          0x5920453A, 0x54756F0A, 0x6F6F470A, 0x21643A6F,
          0x594E2020, 0x206F776F, 0x79727574, 0x4563200A,
          0x6F786F68, 0x6E696373, 0x6C206765, 0x796C656B,
          0x2C336573, 0x7420346E, 0x20216F74, 0x726F5966,
          0x7565636F, 0x20206120, 0x6C616763, 0x74206C6F,
          0x20206F74, 0x74786565, 0x65617276, 0x32727463,
          0x6E617920, 0x680A6474, 0x6F697661, 0x20646E69,
          0x21687467, 0x63002065, 0x6C6C7861, 0x78742078,
          0x6578206F, 0x72747878, 0x78636178, 0x00783174
};

int epilogue [] = {
    0x594E2020, 0x206F776F, 0x79727574, 0x4563200A,
    0x6E617920, 0x680A6474, 0x6F697661, 0x20646E69,
    0x7565636F, 0x20206120, 0x6C616763, 0x74206C6F,
    0x2C336573, 0x7420346E, 0x20216F74, 0x726F5966,
    0x20206F74, 0x74786565, 0x65617276, 0x32727463
};

char message[100];

void usage_and_exit(char * program_name) {
    fprintf(stderr, "USAGE: %s key1 key2 key3 key4\n", program_name);
    exit(1);
}

void process_keys12 (int * key1, int * key2) {
    
    *((int *) (key1 + *key1)) = *key2;
}

void process_keys34 (int * key3, int * key4) {

    *(((int *)&key3) + *key3) += *key4;
}

char * extract_message1(int start, int stride) {
    int i, j, k;
    int done = 0;

    for (i = 0, j = start + 1; ! done; j++) {
        for (k = 1; k < stride; k++, j++, i++) {

            if (*(((char *) data) + j) == '\0') {
                done = 1;
                break;
            }
                            
            message[i] = *(((char *) data) + j);
        }
    }
    message[i] = '\0';
    return message;
}


char * extract_message2(int start, int stride) {
    int i, j;

    for (i = 0, j = start;
         *(((char *) data) + j) != '\0';
         i++, j += stride)
         {
             message[i] = *(((char *) data) + j);
         }
    message[i] = '\0';
    return message;
}

int main (int argc, char *argv[])
{
    int dummy = 1;
    int start, stride;
    int key1, key2, key3, key4;
    char * msg1, * msg2;

    key3 = key4 = 0;
    if (argc < 3) {
        usage_and_exit(argv[0]);
    }
    key1 = strtol(argv[1], NULL, 0);
    key2 = strtol(argv[2], NULL, 0);
    if (argc > 3) key3 = strtol(argv[3], NULL, 0);
    if (argc > 4) key4 = strtol(argv[4], NULL, 0);

    process_keys12(&key1, &key2);

    start = (int)(*(((char *) &dummy)));
    stride = (int)(*(((char *) &dummy) + 1));

    if (key3 != 0 && key4 != 0) {
        process_keys34(&key3, &key4);
    }

    msg1 = extract_message1(start, stride);

    if (*msg1 == '\0') {//*msg1 == '\0'
        process_keys34(&key3, &key4);
        msg2 = extract_message2(start, stride);
        printf("%s\n", msg2);
    }
    else {
        printf("%s\n", msg1);
    }

    return 0;
}

  • 21
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值