逆向练习7

每日逆向的理解和积累。

汇编阅读练习

练习1

1.汇编代码及解释如下:

  • main函数


  • get24函数



  • calculate_model1函数(函数2-5与1类似)

2.对应c语言源码如下:

问题描述——C语言24点问题:在屏幕上输入1〜10范围内的4个整数(可以有重复),对它们进行加、减、乘、除四则运算后(可以任意的加括号限定计算的优先级),寻找计算结果等于24的表达式。例如输入4个整数4、5、6、7,可得到表达式:4*((5-6)+7)=24。这只是一个解,要求输出全部的解。要求表达式中数字的顺序不能改变。

问题分析如下——

算法设计如下——

具体编程实现如下——



3.该程序中值得注意的是浮点数相关的指令及操作:st(i):代表浮点寄存器(st(0)-st(7)),对于浮点操作数所说的出栈、入栈操作都是指对st(i)的操作和影响(如出栈操作指令fst/fstp,入栈操作指令fld

参考链接——

(1)汇编语言:浮点数传送指令;
(2)操作浮点数-汇编层面;
(3)汇编语言浮点数指令集;
(4)汇编浮点数运算指令大全;

练习2

1.汇编代码及解释如下:

  • main函数

  • sortRand函数

  • sortScore函数(函数sortNum与之类似)


  • setRand函数(函数sortNum与之类似)

注意:分析过程中值得注意的是——碰到红框框起来的这种寻址处理方式,可推测是结构体的处理方式,本题中分析出的二维数组的结论是错误的,应该是一个结构体数组,而不是普通的二维数组。

2.对应c语言源码如下:

问题描述——C语言选美比赛:用c语言编写软件完成以下任务:一批选手参加比赛,比赛的规则是最后得分越高,名次越低。当半决赛结束时,要在现场按照选手的出场顺序宣布最后得分和最后名次,获得相同分数的选手具有相同的名次,名次连续编号,不用考虑同名次的选手人数。例如:选手序号: 1,2,3,4,5,6,7 选手得分: 5,3,4,7,3,5,6 输出名次为:3,1,2,5,1,3,4

具体编程实现如下——


练习3

1.汇编代码及解释如下:

  • main函数

  • array函数


2.对应c语言源码如下:

问题描述——C语言实现魔方阵:编写程序,实现如下表所示的5-魔方阵。

具体编程实现如下——

#include<stdio.h>
#include<stdlib.h>
int array(int n)
{
    int i, j, no, num, max;
    int *mtrx;
    if(n%2 == 0)  /*n是偶数,则加1使其变为奇数*/
    {
        n=n+1;
    }
    max=n*n;
    mtrx=(int *)malloc(max+max);  /*为魔方阵分配内存*/
    mtrx[n/2]=1;  /* 将1存入数组*/
    i=0;  /*自然数1所在行*/
    j=n/2;  /*自然数1所在列*/
/*从2开始确定每个数的存放位置*/
    for(num=2; num<=max; num++)
    {
        i=i-1;
        j=j+1;
        if((num-1)%n == 0)  /*当前数是n的倍数*/
        {
            i=i+2;
            j=j-1;
        }
        if(i<0)  /*当前数在第0行*/
        {
            i=n-1;
        }
        if(j>n-1)  /*当前数在最后一列,即n-1列*/
        {
            j=0;
        }
        no=i*n+j;  /*找到当前数在数组中的存放位置*/
        mtrx[no]=num;
    }
/*打印生成的魔方阵*/
    printf("生成的%d-魔方阵为:",n);
    no=0;
    for(i=0; i<n; i++)
    {
        printf("\n");
        for(j=0; j<n; j++)
        {
            printf("%3d", mtrx[no]);
            no++;
        }
    }
    printf("\n");
    free(mtrx);
    return 0;
}
int main()
{
    int n;
    printf("请输入n值:\n");
    scanf("%d", &n);
    array(n);  /*调用array函数*/
    return 0;
}

3.该程序中值得注意的有以下三个问题——

在汇编层面通过and 1 然后判断结果是否为0的操作,来实现c语言中if(n%2==0)的判断奇数偶数的功能;

在分析过程中,如果变量较多,可以边分析边给ida中的各个形如[ebp+var_10]的变量赋予更便于分析的表示如xy等,边分析边尝试还原原本的c代码;

对于魔方矩阵的了解。

练习4

1.汇编代码及解释如下:

  • search函数(由于代码太长,这里只列出来一部分)




注意:分析过程中值得注意的几个问题——

(1)如图中红字描述所示,注意#define N 15这种形式定义的常量在汇编层面上可能的表现形式,以及区分一维数组和二维数组的部分内容。

(2)注意对于if中的多个判断条件的汇编结构的识别(重点关注其结构特征),如下图所示。

2.对应c语言源码如下:

问题描述——C语言农夫过河:一个农夫在河边带了一只狼、一只羊和一颗白菜,他需要把这三样东西用船带到河的对岸。然而,这艘船只能容下农夫本人和另外一样东西。如果农夫不在场的话,狼会吃掉羊,羊也会吃掉白菜。请编程为农夫解决这个过河问题。

具体编程实现如下——

注意:对于该算法和对应编程实现的理解。

练习5

1.汇编代码及解释如下:

  • main函数(由于代码太长,这里只列出来整体框架和其中的一部分)

注意:分析过程中值得注意的几个问题——

(1)如图所示,对于for循环结构的识别和还原。

(2)注意对于if中的多个判断条件的汇编结构的识别(重点关注其结构特征),如下图所示。

2.对应c语言源码如下:

问题描述——C语言委派任务问题:某项任务需要在A、B、C、D、E、F这6个人中挑选人来完成,但挑选人受限于以下的条件:

  • A和B两个人至少去一人;
  • A和D不能同时去;
  • A、E和F三人中要挑选两个人去;
  • B和C同时去或者都不去;
  • C和D两人中只能去一个;
  • 如果D不去,那么E也不去。

试编程求出应该让哪几个人去完成这项任务。。

具体编程实现如下——