[RE]攻防世界--新手区

1.攻防世界--新手区--open-source

下载拿到c语言文件,都不用反汇编,直接观察代码。让他们都if判断失败不就可以最终执行输出key的代码了

#include <stdio.h>
#include <string.h>
​
int main(int argc, char *argv[]) {
   //argc ==4
    if (argc != 4) {
        printf("what?\n");
        exit(1);
    }
//first ==0xcafe
    unsigned int first = atoi(argv[1]);
    if (first != 0xcafe) {
        printf("you are wrong, sorry.\n");
        exit(2);
    }
//这个地方其实我不确定不同的答案能否拿到相同的结果,所以我用python跑了一下
    unsigned int second = atoi(argv[2]);
    if (second % 5 == 3 || second % 17 != 8) {
        printf("ha, you won't get it!\n");
        exit(3);
    }
//这个地方让argv[3] == h4cky0u
    if (strcmp("h4cky0u", argv[3])) {
        printf("so close, dude!\n");
        exit(4);
    }
​
    printf("Brr wrrr grr\n");
//我在这里加了一个printf("%d    %d",first,strlen(argv[3]));
    unsigned int hash = first * 31337 + (second % 17) * 11 + strlen(argv[3]) - 1615810207;
​
    printf("Get your key: ");
    printf("%x\n", hash);
    return 0;
}
​

用python代码及输出结果

for i in range(1000):
    if i%5!=3 and i%17==8:
        print(hex(51966 * 31337 + (i % 17) * 11 + 7 - 1615810207))
​

发现输出结果相同,成功提交。

题后思考

该题目中出现的问题以及自己的一些见解:

1. argc == 4不能成功通过第一个if,这个没找到原因(当然第一个判断也没啥用)
2.argc是命令行总的参数个数,也就是说一共有4个参数;argv[]存放的是main函数的参数,argv[]是字符串数组(我当时以为是指针数组,存放的是指针,现在想想感觉也没问题,毕竟指针指向的也是字符串不是)第0个参数是程序的全名,依次是用户通过命令行输入的参数。
3. strcmp()这个函数相同返回0,不同返回1!!!

2.攻防世界--新手区--python-trade

pyc文件直接反汇编,生成.pyc_dis,notepad++打开

# Embedded file name: 1.py
import base64
​
def encode(message):
    s = ''
    for i in message:
        x = ord(i) ^ 32
        x = x + 16
        s += chr(x)
​
    return base64.b64encode(s)
​
​
correct = 'XlNkVmtUI1MgXWBZXCFeKY+AaXNt'
flag = ''
print 'Input flag:'
flag = raw_input()
if encode(flag) == correct:
    print 'correct'
else:
    print 'wrong'

由以上可以看出来逻辑是:对flag加密,加密之后==correct,加密方法就是encode。逆向逻辑:对encode进行逆向。

代码如下:

import base64
def decode(message):
    s = base64.b64decode(message)
    st = ''
    for i in s:
        #print(type(i))可以使用这种方式测试i的类型
        tmp = i - 16
        #tmp = ord(i)-16
        # 这里运行会出错的原因是ord()函数接受的类型是一个长度为1的字符串,
        # 而在python3当中传入的i已经是一个整型数了(b64decode()函数返回值就是16进制数),
        #所以直接i-16就可以。网上的其他blog中提到py2不会出现这种问题,做了测试,
        # py2上述语法确实不会出问题,但是会报新的错误
        tmp = tmp^32
        st += chr(tmp)
    return st
correct = 'XlNkVmtUI1MgXWBZXCFeKY+AaXNt'
str = decode(correct)
print(str)
​
​

题后思考

见代码注释

3.攻防世界--新手区--re1

拿到一个exe文件,查壳,发现32位无壳exe,ida打开,直接找到main函数

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // eax
  __int128 v5; // [esp+0h] [ebp-44h]
  __int64 v6; // [esp+10h] [ebp-34h]
  int v7; // [esp+18h] [ebp-2Ch]
  __int16 v8; // [esp+1Ch] [ebp-28h]
  char v9; // [esp+20h] [ebp-24h]
​
  _mm_storeu_si128((__m128i *)&v5, _mm_loadu_si128((const __m128i *)&xmmword_413E34));
  v7 = 0;
  v6 = qword_413E44;
  v8 = 0;
  printf("欢迎来到DUTCTF呦\n");
  printf("这是一道很可爱很简单的逆向题呦\n");
  printf("输入flag吧:");
  scanf("%s", &v9);
  v3 = strcmp((const char *)&v5, &v9);
  if ( v3 )
    v3 = -(v3 < 0) | 1;
  if ( v3 )
    printf(aFlag_0);
  else
    printf((const char *)&dword_413E90);
  system("pause");
  return 0;
}

根据反汇编看逻辑:v9也就是flag,v9和v5做比较,不同为1,执行if语句,使出aFlag_0(见下图)相同为0,直接执行else语句,输出dword_413E90(见下图)

 

 

逻辑分析清楚之后,就找到v5即可,对v5有操作的函数只有 _mm_storeu_si128()函数,经查询发现,这是常用指令

指令名:void _mm_store_si128 ( __m128i *p, __m128i a);
​
功能:可存储128位数据;
​
说明:将__m128i 变量a的值存储到p所指定的变量中去;
注意:p必须是一个16-bit对齐的一个变量的地址。

查看xmmword_413E34,

 

因为是小端存储,将字符串逆置一下就可以。

我当时做的时候,发现下面有qword_413E44,因为是小端存储,逆置将他们连接,成功提交。

 

其他解题方法

  1. 判断出xmmword之后,直接去16进制中搜索DUTCTF,可以拿到flag 

  2. 动态调试

这个地方手贱非得ida动调(主要是喜欢ida那种有反汇编的调试),失败了(失败原因是ida需要使用7.5版本的ida pro),在寄存器窗口的ECX中可以看到,跳转地址直接去,转成字符串,直接有flag。

 

od动调(虚拟机的od也失败了,本机装了个od,成功打开,然后因为自己动调太菜了,没调出来,哭哭了)

         3. 打开文件的时候直接二进制文件打开,直接搜就有flag

题后思考

  1. 反汇编代码存在一定问题,并未对v6进行操作就v5就自动连接了(未解决)

  2. _mm_storeu_si128()函数

  3. 字符串逆置方式()

  4. 动调能力太差

4.攻防世界--新手区--game

idapro打开,f5反汇编查看逻辑

我的断点直接下在了if判断上,然后修改寄存器的值,保证每个cmp都能够执行

 

由上图可以看出,虽然没有全部显现亮灯,但是显示了flag

其他解题方法

后来看人家的wp,我更无语了。

方法1:这个game竟然是输入12345678,自己就出flag(现在想想也合理,因为他是先判断1,在判断2,依次判断的,我只能说还是自己太菜了,get到了)

方法2:静态反汇编 发现自己的ida跟博主的ida显示不同,所以我换了个版本的ida打开

 

这个就比较明显,v2-v58是前面的,剩下的是后面的,写个脚本即可

a = [18,64,98,5,2,4,6,3,6,48,49,65,32,12,48,65,31,78,62,32,49,32,
       1,57,96,3,21,9,4,62,3,5,4,1,2,3,44,65,78,32,16,97,54,16,44,
       52,32,64,89,45,32,65,15,34,18,16,0]
b = [123,32,18,98,119,108,65,41,124,80,125,38,124,111,74,49,
       83,108,94,108,84,6,96,83,44,121,104,110,32,95,117,101,99,
       123,127,119,96,48,107,71,92,29,81,107,90,85,64,12,43,76,86,
       13,114,1,117,126,0]
for i in range(len(a)) :
    b[i] = b[i] ^a[i]
    b[i] = b[i] ^0x13
    print(chr(b[i]),end="")

题后思考

这个题静态反汇编逻辑出现问题,因为我找到的核心函数是sub_6fa7be,但是这个函数最下面的比较应该是可以出flag的,我找出来的v3长度只有22,没法进行异或,所以改变了方式,使用了动态调试的方法。

buu做过,但是当时是静态逆出来的,无语了

5.攻防世界--新手区--Hello, CTF

ida打开,main函数,拿到一串字符串

 

 

静态逻辑分析,发现,v10跟v13相同就输出success,此时我并不清楚v9跟v13哪个是flag,v9根据逻辑可以看出来是17位长度,然后把v9中的数据存放到buffer中(此处sprintf函数功能是猜测的,因为这里并没有输出操作),然后把buffer追加到v10后面就可以了。可以发现v13是16进制数,输出一下字符串,得到flag

s=bytes.fromhex("437261636b4d654a757374466f7246756e")
print(s)

动态调试尝试过,但是因为这题就是单纯的对比,调试成功也是显示success,没有很大的用处。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值