CTF 【每日一题20160701】breakpoint(未解决)

breakpoint
来源:http://ctf.idf.cn/index.php?g=game&m=article&a=index&id=46
请看这里: http://pan.baidu.com/s/1pJyUYEZ
下载后得到一个文件:Elfcrackme2


本题分析
我的思路受以下文章启发,表示诚挚谢意:

1.又是一个elf执行文件,还是用idapro64打开它,如下图:
这里写图片描述

另外,有几个linux下的命令,虽然对于解本题意义不如idapro的用处大,但作为linux自带的程序员工具,还是说说:

  • readelf
    • 该命令是Linux下的分析ELF文件的命令,这个命令在分析ELF文件格式时非常有用
    • 命令格式:readelf elf文件名
  • strings
    • 可以打印出文件中所有列出的可打印字符串
    • 格式:strings 文件名
  • file
    • 用于检测文件类型
    • 格式:file 文件名
  • gdb
    • 用于调试linux下程序
    • 命令参数太多,最简单:gdb 文件名
  • objdump

    • 用于输出可执行文件的汇编代码
    • 格式:objdump -D 可执行文件名 > out.asm

    效果如下图:
    readelf命令
    这里写图片描述
    file命令
    这里写图片描述
    strings命令
    这里写图片描述

2.遍历点击左侧函数名,查看右侧内容,发现有个名为sub_80483B0的函数里面内容有我们关注的类似“flag…”输出语句。按F4调用cpp反编译插件,如下图:
这里写图片描述

值得分析的关键代码如下:

unsigned char g8049908 = 0xff;
unsigned char g80498f0 = 24;
unsigned char g8049909 = 0xff;
unsigned char g80498f1 = 91;
unsigned char g804990a = 0xff;
unsigned char g80498f2 = 0xbf;
signed char g804990b = -1;
signed char g80498f3 = 56;
signed char g804990c = -1;
signed char g80498f4 = 52;
signed char g804990d = -1;
signed char g80498f5 = 90;
signed char g804990e = -1;
signed char g80498f6 = 0x99;
signed char g804990f = -1;
signed char g80498f7 = 77;
signed char g8049910 = -1;
signed char g80498f8 = 46;
signed char g8049911 = -1;
signed char g80498f9 = 0x73;
signed char g8049912 = -1;
signed char g80498fa = -69;
signed char g8049913 = -1;
signed char g80498fb = 78;
uint32_t g8049914 = 0xffffffff;
signed char g80498fc = 35;
unsigned char g80498fd = 0x76;
unsigned char g80498fe = 0x9f;
unsigned char g80498ff = 3;
...
void sub_80483B0() {
    signed char* ebx1;
    uint32_t eax2;
    signed char* edx3;
    uint32_t edx4;
    uint32_t v5;
    uint32_t edx6;
    uint32_t ecx7;
    uint32_t ecx8;
    uint32_t ebx9;
    uint32_t edi10;
    uint32_t ebx11;
    uint32_t ebx12;
    uint32_t ebx13;
    uint32_t ebx14;
    uint32_t ebx15;
    uint32_t ebx16;
    uint32_t ebx17;
    uint32_t ebx18;
    uint32_t ebx19;
    uint32_t eax20;
    uint32_t ebx21;

    printf("%s\nPlease input your flag:", g8049900);
    __isoc99_scanf("%s", 0x8049908);
    ebx1 = g8049900;
    eax2 = (uint32_t)ebx1 - (uint32_t)sub_80483B0;
    if ((uint32_t)ebx1 > (uint32_t)sub_80483B0) {
        edx3 = (signed char*)sub_80483B0;
        do {
            ++edx3;
            eax2 = eax2 << 5 ^ (uint32_t)((int32_t)eax2 >> 27) ^ (uint32_t)(unsigned char)*edx3;
        } while (edx3 != ebx1);
    }
    edx4 = eax2;
    v5 = eax2;
    if ((*(unsigned char*)&edx4 ^ g8049908) != g80498f0 || ((edx6 = (uint32_t)(unsigned char)*((signed char*)&v5 + 1), ecx7 = edx6, (*(unsigned char*)&ecx7 ^ g8049909) != g80498f1) || ((ecx8 = (uint32_t)(unsigned char)*((signed char*)&v5 + 2), ebx9 = ecx8, (*(unsigned char*)&ebx9 ^ g804990a) != g80498f2) || ((edi10 = (uint32_t)(unsigned char)*((signed char*)&v5 + 3), ebx11 = (uint32_t)(unsigned char)g804990b ^ edi10, *(signed char*)&ebx11 != g80498f3) || ((ebx12 = (uint32_t)(unsigned char)g804990c ^ eax2, *(signed char*)&ebx12 != g80498f4) || ((ebx13 = (uint32_t)(unsigned char)g804990d ^ edx6, *(signed char*)&ebx13 != g80498f5) || ((ebx14 = (uint32_t)(unsigned char)g804990e ^ ecx8, *(signed char*)&ebx14 != g80498f6) || ((ebx15 = (uint32_t)(unsigned char)g804990f ^ edi10, *(signed char*)&ebx15 != g80498f7) || ((ebx16 = (uint32_t)(unsigned char)g8049910 ^ eax2, *(signed char*)&ebx16 != g80498f8) || ((ebx17 = (uint32_t)(unsigned char)g8049911 ^ edx6, *(signed char*)&ebx17 != g80498f9) || ((ebx18 = (uint32_t)(unsigned char)g8049912 ^ ecx8, *(signed char*)&ebx18 != g80498fa) || ((ebx19 = (uint32_t)(unsigned char)g8049913 ^ edi10, *(signed char*)&ebx19 != g80498fb) || ((eax20 = eax2 ^ g8049914, *(signed char*)&eax20 != g80498fc) || ((*(unsigned char*)&edx6 ^ *((unsigned char*)&g8049914 + 1)) != g80498fd || ((*(unsigned char*)&ecx8 ^ *((unsigned char*)&g8049914 + 2)) != g80498fe || (ebx21 = edi10, (*(unsigned char*)&ebx21 ^ *((unsigned char*)&g8049914 + 3)) != g80498ff)))))))))))))))) {
        puts("You are wrong", 0x8049908);
    } else {
        puts("You are right", 0x8049908);
    }
    return;
}

3.先分析一下输出“You are wrong”前if语句表达式的含义,由于里面进行异或运算,所以要留意一下变量占的字节数(这里都是一个字节),如果变量字节都是1Byte,那么很长的if表达式就可简化为下列表达式:

 if ((edx4 ^ 0xff ) != 24 
    || ((edx6 = v5 + 1), ecx7 = edx6, (ecx7 ^ 0xff) != 91) 
    || ((ecx8 = v5 + 2), ebx9 = ecx8, (ebx9 ^ 0xff) != 0xbf) 
    || ((edi10 = v5 + 3), ebx11 = -1 ^ edi10, ebx11 != 56) 
    || ((ebx12 = -1 ^ eax2, ebx12 != 52) 
    || ((ebx13 = -1 ^ edx6, ebx13 != 90) 
    || ((ebx14 = -1 ^ ecx8, ebx14 != 0x99) 
    || ((ebx15 = -1 ^ edi10, ebx15 != 77) 
    || ((ebx16 = -1 ^ eax2, ebx16 != 98f8) 
        || ((ebx17 = -1 ^ edx6, ebx17 != 0x73) 
            || ((ebx18 = -1 ^ ecx8, ebx18 != -69) 
                || ((ebx19 = -1 ^ edi10,ebx19 != 78)
                    || ((eax20 = eax2 ^ 0xffffffff, eax20 != 35) 
                        || ((*(unsigned char*)&edx6 ^ *((unsigned char*)&0xffffffff + 1)) != 0x76 
                            || ((*(unsigned char*)&ecx8 ^ *((unsigned char*)&0xffffffff + 2)) != 0x9f 
                                || (ebx21 = edi10, (*(unsigned char*)&ebx21 ^ *((unsigned char*)&0xffffffff + 3)) != 3)
                                )
                            )
                        )
                    )
                )
            )
        )
        )
        )
        )
        )
        )
    {
        puts("You are wrong", 0x8049908);
    } else {
        puts("You are right", 0x8049908);
    }
    return;

我做了几天,都没有找出线索,现在记录一下中间结果,期待后期进步后解决

edx2 = 231
    -----
    edx4 = 231
    edx6 = 164
    edx7 = 164
    edx9 = 40   (
    ebx11 = 56   8
    ebx12 = 52   4
    ebx13 = 90    Z
    ebx14 = 153
    ebx15 = 77     M

    ebx16 = 46     .
    ebx17 = 115     s
    ebx18 = -69
    ebx19 = 78      N

    eax20 =35       #
    g8049914 = edx2 xor eax20 = 1960xffffffff0xffffffff        210
    ecx8 xor 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值