BUU_RE学习记录1

一、easyre

1.010打开,直接搜flag,得到flag

image

二、reverse1

1.先查壳,得知是64位无壳,直接用IDA打开

image

2.shiftF12查找字符串,发现关键语句

image

3.查看相应代码,F5反编译

image

4.发现关键的比较函数,看一下分别比较的字符串

image

5.发现是输入的str1和程序中的str2({hello_world})相比较,那么flag就是

image

三.reverse2

1.查壳,64位,非exe

image

2.IDA打开,shift12发现关键语段

image

3.找到对应的函数,发现是一个将flag和输入的字符串进行对比

image

4.代码表现出了flag的加密过程,但是根据代码的判断应该会存在一个原flag字符串,回去查找字符串,发现了一个特殊意义的str

image

5.之前提到的flag加密代码的含义就是逐个遍历flag的字符,如果字符为i或者r,那就把它改为1。直接写个脚本跑一下(或者可直接手动)。

点击查看代码
#include <iostream>
#include <stdlib.h>
#include <stdio.h>

int main() {
    int i = 0;
    char flag[] = "hacking_for_fun}";
    for (i = 0; i <= 15; ++i)
    {
        if (flag[i] == 'i' || flag[i] == 'r')
            flag[i] = '1';
    }
    printf("%s", flag);
	return 0;
}

6.得到flag

flag{hack1ng_fo1_fun}

四.内涵的软件

1.查壳,无壳,IDA(非64位)打开,进入main函数,进入main_0函数

image

2.找到一串字符串,就是flag(改一下前面的头)

image

flag{49d3c93df25caad81232130f3d2ebfad}

五、新年快乐

1.查壳,发现是UPX

image

2.使用UPXshell解压缩去壳

image

3.IDA(非32位)打开,找到main函数,发现关键语句

image

4.根据比较函数发现,str2就是flag的正确形式,再看str2的来源,是使用了strcpy函数,那么flag就是HappyNewYear!

flag{HappyNewYear!}

六、xor

1.查壳,发现是64位无壳,使用IDA打开,找到main函数

image

2.代码的意思就是将首先判断长度是否为33,不是就failed,然后如果长度正确,就使用for循环由后一个异或前一个。找到原来的字符串

image

3.写个脚本,利用异或的特点,得到flag(需要注意到的是有一些字符本身就是ASCII码,不能再将其转为ASCII码,否则会异或出错)

点击查看代码
s = ['f','10','k','12','w','&','O','.','@','17','x','13','Z',';','U','17','p','25','F','31','v','"','M','#','D','14','g','6','h','15','G','2','O','0']
ls = []
for i in range(0,len(s)):
    if len(s[i]) > 1 or s[i] == '6' or s[i] == '0':
        ls.append(int(s[i]))
    else:
        ls.append(ord(s[i]))
for i in range(1,33):
    print(chr(ls[i] ^ ls[i - 1]),end = '')

4.得到flag(直接异或得到的字符串前面少一个f)

flag{QianQiuWanDai_YiTongJiangHu}

七、helloword

1.得到一个apk文件,使用IDA打开,注意选择APK

image

2.shiftF12搜索字符串,发现flag

image

flag{7631a988259a00816deda84afb29430a}

八、reverse3

1.查壳,无壳,使用IDA(非64)打开

image

2.shift12搜索字符串,看到了base64和加密表以及关键词flag

image

3.追踪找到关键函数

image

4.关键函数代码审计一下,简单来说就是先将输入的str经过base64加密然后逐位与0123...相加,然后与str2进行比较,str2可以直接找到。直接写脚本逆回去

点击查看代码
str = "e3nifIH9b_C@n@dH"
s = list(str)
ls = ''
for i in range(len(s)):
    ls += chr(ord(s[i]) - i)

print(base64.b64decode(ls))

image

5.运行后得到flag

flag{i_l0ve_you}

image

九、不一样的flag

1.查壳,无壳,使用IDA(非64)打开,shiftF12查找字符串

image

2.发现一串01串,觉得像迷宫题,进入到函数

image

3.果然是迷宫题,根据最后的输出语句可以得知flag就是走出迷宫的1234选择,根据exit()函数可以得知遇到1就退出,那就是从头走到尾同时只走0

image

4.01串一共是25个字符,那就是5x5的矩阵

image

5.直接目测,得到flag

222441144222

十、SimpleRev

1.查壳,无壳,使用IDA(64位)打开

image

2.shiftF12发现关键语句

image

3.找到关键的程序函数main函数中的Decry()函数

点击查看代码
unsigned __int64 Decry()
{
  char v1; // [rsp+Fh] [rbp-51h]
  int v2; // [rsp+10h] [rbp-50h]
  int v3; // [rsp+14h] [rbp-4Ch]
  int i; // [rsp+18h] [rbp-48h]
  int v5; // [rsp+1Ch] [rbp-44h]
  char src[8]; // [rsp+20h] [rbp-40h] BYREF
  __int64 v7; // [rsp+28h] [rbp-38h]
  int v8; // [rsp+30h] [rbp-30h]
  __int64 v9[2]; // [rsp+40h] [rbp-20h] BYREF
  int v10; // [rsp+50h] [rbp-10h]
  unsigned __int64 v11; // [rsp+58h] [rbp-8h]

  v11 = __readfsqword(0x28u);
  *(_QWORD *)src = 0x534C43444ELL;
  v7 = 0LL;
  v8 = 0;
  v9[0] = 0x776F646168LL;
  v9[1] = 0LL;
  v10 = 0;
  text = (char *)join(key3, v9);
  strcpy(key, key1);
  strcat(key, src);
  v2 = 0;
  v3 = 0;
  getchar();
  v5 = strlen(key);
  for ( i = 0; i < v5; ++i )
  {
    if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 )
      key[i] = key[v3 % v5] + 32;
    ++v3;
  }
  printf("Please input your flag:");
  while ( 1 )
  {
    v1 = getchar();
    if ( v1 == 10 )
      break;
    if ( v1 == 32 )
    {
      ++v2;
    }
    else
    {
      if ( v1 <= 96 || v1 > 122 )
      {
        if ( v1 > 64 && v1 <= 90 )
        {
          str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
          ++v3;
        }
      }
      else
      {
        str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
        ++v3;
      }
      if ( !(v3 % v5) )
        putchar(32);
      ++v2;
    }
  }
  if ( !strcmp(text, str2) )
    puts("Congratulation!\n");
  else
    puts("Try again!\n");
  return __readfsqword(0x28u) ^ v11;
}

4.代码审计,首先看比较函数,得知是将text和str2相比较,str2目前找不到相应的字符串,text是由 join(key3, (const char *)v9);组成,key3追踪可得是kills,v9在代码的前面部分,查看十六进制可以看出是大端序存储的,但是在CPU和x86中一般为小端序存储,那么原本的字串就是IDA中转为char后倒转一下

image

5.所以src = NDCLS , v9 = hadow,再查看join函数的源码,可以看出作用就是将key3和v9连接在一起

image

6.所以text=killshadow,接着向下,strcpy(key, key1),key1=ADSFK,将key1复制为key,key=key1=ADSFK;strcat(key, src),将key和src连接,key = ADSFKNDCLS;v5就是key的长度,为10,接下来for循环函数的作用就是判断字符是否为大写,如果为大写就将其变为小写

image

7.接下来就是主要的输入字串处理,而最后与text对比的str2仅由一句话决定str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97,text已经知道了,直接写脚本跑一下

点击查看代码
v3 = 0
key = 'adsfkndcls'
text = 'killshadow'
key = list(key)
text = list(text)
for i in range(10):
    for j in range(128):
        if (j < ord('A') or j > ord('Z')) or (j < ord('z') and j > ord('a')):
            continue
        if ((j - 39 - ord(key[v3 % 10]) + 97) % 26 + 97 == ord(text[i])):
            print(chr(j),end='');
            v3 += 1
            break

8.需要注意,因为源码中的key在与str2比较前,经过一个函数转变全部为小写字母,所以写脚本时使用的key也应是小写字母

image

9.得到flag

KLDQCUDFZO

十一、[GXYCTF2019]luck_guy

1.查壳,无壳,IDA(64)打开

image

2.发现关键词以及一半像flag的东西

image

3.直接进入get_flag()函数里,可以看到一个随机数机制

image

4.直接代码审计一下,简单函数的意思就是通过switch()函数和随机数生成的机制会随组成一些字串,其中就有flag,可以看出只有case1、case4、case5会实际上对字串的组合产生改变

image

5.case1是将f1和f2连接在一起输出,f1可追踪得到字串,f2为空

image

6.case4是将s2赋值为s

image

7.case5是通过一个for循环改变f2中字串的形式,那就可以直接分析出,只有运行451的顺序,才会生成有效的字串(就是将f1、f2全都利用上)

image

8.直接写脚本

点击查看代码
f1 = 'GXY{do_not_'
s = [0x69,0x63,0x75,0x67,0x60,0x6f,0x66,0x7f,0]
f1 = list(f1)
for i in range(8):
    if i % 2 == 1:
        f1.append(chr(int(s[i]) - 2))
    else:
        f1.append(chr(int(s[i]) - 1))
for i in range(len(f1)):
    print(f1[i],end = '')

9.得到flag

GXY{do_not_hate_me}

image

十二、[BJDCTF2020]JustRE

1.查壳,无壳,使用IDA(非64)打开

image

2.查看字符串,发现一串很像flag

image

3.进入函数看看,直接就可以找到flag(记得将%d替换为正常输出的数据)

image

4.得到flag

BJD{1999902069a45792d233ac}

十三、刮开有奖

1.查壳,无壳,IDA(非64)打开

image

2.查看字符串,看到一串很像字母表的字串,猜测是什么的加密表,进入DialogFunc函数(或者从winmain函数中进入DialogFunc函数)

image

3.按照顺序从前往后跑一遍,主要的加密函数是从 if ( strlen(String) == 8 )开始,接下来是v7-v16的赋值,然后进入了sub_4010F0()函数,点进去这个函数可以发现是将传入的数据进行了处理,而传入的数据就是前面的v7-v16,那么我们首先就要先得到经过函数处理后的加密的字符串,将sub_4010F0()函数伪代码整理一下为编译器可编译的C语言代码(注:代码中因为将a1改为了char类型的数组,而伪代码中a1为int型,本程序为32位,而在32位机中,char占1个字节,int占4个字节,所以其中涉及到地址位移偏量的4就在可编译代码中没有了),注意自己填上主函数

点击查看代码
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
int  sub_4010F0(char* a1, int a2, int a3)
{
  int result; // eax
  int i; // esi
  int v5; // ecx
  int v6; // edx

  result = a3;
  for ( i = a2; i <= a3; a2 = i )
  {
    v5 = i;
    v6 = a1[i];
    if ( a2 < result && i < result )
    {
      do
      {
        if ( v6 > a1[result] )
        {
          if ( i >= result )
            break;
          ++i;
          a1[v5] = a1[result];
          if ( i >= result )
            break;
          while ( a1[i] <= v6 )
          {
            if ( ++i >= result )
              goto LABEL_13;
          }
          if ( i >= result )
            break;
          v5 = i;
          a1[result] = a1[i];
        }
        --result;
      }
      while ( i < result );
    }
LABEL_13:
    a1[result] = v6;
    sub_4010F0(a1, a2, i - 1);
    result = a3;
    ++i;
  }
  return result;
}

int main(){
	char a1[] = "ZJSECaNH3ng";
	sub_4010F0(a1, 0, 10);
	printf("%s",a1);
	return 0;
}

image
image

4.得到加密后的字串

3CEHJNSZagn

image

5.接着向下,可以看到v4和v5都是由v18进入sub_401000()处理后得到,点进函数看一下,发现有点儿复杂,看到一个特殊的数据byte_407830,点进去看一下,发现是字符表,猜测这个函数的作用就是base64加密

image

6.根据strcmp函数可以看出加密后的v4=ak1w,v5=V1Ax,那就base64解密一下,得到加密前的v4=jMp,v5=WP1,然后看最后的if语句

image

7.String[0] = v7[0]+34 = U, String[1] = v10 = J, String[2] = (3v8+141) = 87 = W, String[3] = 2(v13/9)*4 = 80 = P,那么根据之前base64解密后得到的字符串就可以确定flag了,v5在前v4在后

flag{UJWP1jMp}

十四、简单注册器

1.得到apk文件,使用IDA(APK)打开后发现无法反汇编,使用jeb打开

image

2.按tab键进行反编译,可以找到得到flag的那段代码

image

3.稍微处理一下,写个脚本跑一下就得到flag了

点击查看代码
str = "dd2940c04462b4dd7c450528835cca15"
str = list(str)
str[2] = (chr(ord(str[2]) + ord(str[3]) - 50));
str[4] = (chr(ord(str[2]) + ord(str[5]) - 0x30));
str[30] = (chr(ord(str[0x1F]) + ord(str[9]) - 0x30));
str[14] = (chr(ord(str[27]) + ord(str[28]) - 97));

for i in range(16):
    v0 = str[0x1F - i]
    str[0x1F - i] = str[i]
    str[i] = v0

for i in str:
    print(i,end='')

4.得到flag

flag{59acc538825054c7de4b26440c0999dd}

image

十五、[GWCTF 2019]pyre

1.得到一个pyc文件,pyc文件是可执行的字节码文件,通过反编译可变为py文件,在线反编译一下

网站:https://tool.lu/pyc/

2.得到py文件,需要注意反汇编后的是python2.7的代码

image

3.按照代码的逻辑逆回去,一共经过了两次处理,代码如下

点击查看代码
code = ['\x1f','\x12','\x1d','(','0','4','\x01','\x06','\x14','4',
        ',','\x1b','U','?','o','6','*',':','\x01','D',';','%','\x13']
code.reverse()

for i in range(len(code)-1):
    code[i + 1] = chr(ord(code[i]) ^ ord(code[i+1]))
code.reverse()
for i in range(len(code)):
    print(chr((ord(code[i])-i)%128),end="")

4.得到flag

GWHT{Just_Re_1s_Ha66y!}

image

十六、[ACTF新生赛2020]easyre

1.查壳,32位,用UPXShell脱个壳,IDA(非64)打开

image

2.shiftF12搜索字串,发现关键字串,追踪函数

image

3.可以发现flag的值与输入的字串ACTF{}无任何关系,主要就是for循环,通过观察for函数可以发现flag的长度为12,主要比较为v4中的字符和data表中的以flag的ASCII码值+i-1为下标的字符,写个脚本(子表直接追踪可得)

image

点击查看代码

v5 = "~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)(" + chr(0x27) + '&%$# !"'
v5 = list(v5)
v4 = r"*F'\"N,\"(I?+@"
v4 = list(v4)
flag = []
for i in v4:
    cnt = 0
    for j in v5:
        if ord(i) != ord(j):
            cnt += 1
        else:
            break
    flag.append(cnt + 1)

for i in flag:
    print(chr(i),end='')

4.得到flag,但是要把#去掉

flag{U9X_1S_W6@T?}

image

posted @ 2022-12-18 18:03  CPYQY_orz  阅读(3377)  评论(0编辑  收藏  举报