XCTF第二题

155 阅读2分钟

本文已参与「新人创作礼」活动, 一起开启掘金创作之路

解题方法写在代码注释里了 题目:

image.png

#include <stdio.h>

#include <string.h>

//大概阅读整体代码,通过最后几行代码我们得知我们需要的flag就是代码中的hash变量

//此时我们逆向推到hash变量的来源

//1.hash值由fist、second和argv[3]三个变量来决定,那我们就跟踪这三个变量

//2.fist变量在第二个if语句中,提示如果first不等于0xcafe的话就退出程序,那我们按照作者意思肯定要让程序执行到显示flag

//那就必须使first=0xcafe

//3.接下来我们再找着second变量,发现second在第三个if语句,提示如果second % 5 == 3 || second % 17 != 8的话就退出,我们目的

//就是执行到最后,那我们就直接用穷举法找到一个数满足second % 5 != 3 && second % 17 == 8

//函数:                unsigned int GetNum = 0;

//                                do{

//                                        if(GetNum % 5 != 3 && GetNum % 17 == 8)

//                                                        {

//                                                                printf("GetNum:%d",GetNum);

//                                                                break;

//                                                        }

//                                        GetNum++;

//                                        }while(1);

//最后得到GetNum = 25,也就是second是25

//4.最后argv[3]可从最后一个if得知argv[3]=h4cky0u

//5.那我们带进hash中去算

//unsigned int hash =0xcafe * 31337 + (25 % 17) * 11 + strlen("h4cky0u") - 1615810207;

//注意最后一行代码要以十六进制输出才能得到flag

//z最后flag为c0ffee

//6.提交显示正确了

int main(int argc, char *argv[]) {

        if (argc != 4) {

                printf("what?\n");

                exit(1);

        }

 

        unsigned int first = atoi(argv[1]);

        if (first != 0xcafe) {

                printf("you are wrong, sorry.\n");

                exit(2);

        }

 

        unsigned int second = atoi(argv[2]);

        if (second % 5 == 3 || second % 17 != 8) {

                printf("ha, you won't get it!\n");

                exit(3);

        }

 

        if (strcmp("h4cky0u", argv[3])) {

                printf("so close, dude!\n");

                exit(4);

        }

 

        printf("Brr wrrr grr\n");

 

        unsigned int hash = first * 31337 + (second % 17) * 11 + strlen(argv[3]) - 1615810207;

 

        printf("Get your key: ");

        printf("%x\n", hash);

        return 0;

}

Tip:CTF普遍做题思维:

  • 尽可能查找可疑字符串,并分析所引用函数
  • 找到关键验证点,比如提示失败成功之类的逻辑处
  • 查看main函数逻辑结合运行cm大致分析得到程序整体运行逻辑
  • 跟踪分析flag最后一次加密结果作位左值的任何地方
  • 查找分析最后一次flag加密结果与任何我们人为操作数据的关系(比如最后一次flag加密结果和我们输入的字符串的关系)
  • 综合上面的方法便可排除干扰项从而利用最后一次flag加密结果逆向推导得到人为操作数据(通常就是正确的flag)