BUUCTF-逆向

BUUCTF-逆向

1.easyre

先用虚拟机看看是多少位的文件;
在这里插入图片描述
拖进IDA看看,一下子就出来了;
在这里插入图片描述

2.reverse1

先用虚拟机看看是多少位的文件;
在这里插入图片描述
打开IDA,查找字符串;
点击View->Open subviews->Strings
在这里插入图片描述
然后观察伪代码
在这里插入图片描述
所有的 ’ o ’全都变成 ’ 0 ‘ ;

flag{hell0_w0rld}

3.reverse2

一样的看看文件是多少位的;
在这里插入图片描述
在IDA中F5反汇编,得到伪代码;
在这里插入图片描述
大概意思是如果字符串里面有 ’ i ’ 或者 ‘ r ',则变更成 ’ 1 ‘ ;

在IDA中,找字符串,找到了flag;
在这里插入图片描述
所以根据代码提示
最终flag为

flag{hack1ng_fo1_fun}

4.内涵的软件

查看位数
在这里插入图片描述
工具查看一下,无壳;
在这里插入图片描述
IDA32位打开就有,简单的考验眼力;
在这里插入图片描述

flag{49d3c93df25caad81232130f3d2ebfad}

5.新年快乐

查壳一查,发现有壳;在这里插入图片描述
拖到虚拟机里面去脱壳;
在这里插入图片描述
然后file一下,看出是32位的,再拖到IDA里面去看看
在这里插入图片描述
主函数很简单,就不用细说了,就是一个比较,
得到flag为:

flag{HappyNewYear!}

6.helloword

是一个apk文件,android逆向;
用APKIDE打开附件
搜索flag在这里插入图片描述

flag{7631a988259a00816deda84afb29430a}

7.xor

异或运算,没有加壳;
拖进IDA看一下;
在这里插入图片描述
逻辑很简单,就是把下一个和之前的一个异或,然后保存。
在这里插入图片描述
这里的数据比较奇怪了,既有数据,又有字符。所以不要单纯的复制下来,要转换为ascii码,然后进行异或,最后贴上脚本。

a=[0x66,0x0A,0x6b,0x0C,0x77,0x26,
   0x4f,0x2e,0x40,0x11,0x78,0x0D,
   0x5a,0x3b,0x55,0x11,
   0x70,0x19,0x46,0x1F,0x76,0x22,
   0x4d,0x23,0x44,0x0E,0x67,
   0x06,0x68,0x0F,0x47,0x32,0x4f]
s=' '
s+='f'
for i in range(1,len(a)):
    s+=chr(a[i]^a[i-1])
print(s)

得出来flag;

flag{QianQiuWanDai_YiTongJiangHu}

8.reverse3

首先打开IDA返汇编得到伪代码;
在这里插入图片描述
点击Str2,看一下其中的内容;
在这里插入图片描述
然后点击sub_4110BE,看一下加密运算;
在这里插入图片描述
发现使用了这个进行数组变换,跟进发现就是之前的base64。
首先for循环将Dest每一位都加了j,所以写脚本还原v1,然后进行base64解码

import base64

str='e3nifIH9b_C@n@dH'
flag=' '
for i in range(len(str)):
    flag+=chr(ord(str[i])-i)
flag=base64.b64decode(flag)
print(flag)

得到flag

flag{i_l0ve_you}

9.不一样的flag

使用IDA一打开就看到一个可以数据;在这里插入图片描述
以为是十六进制编码啥的,发现都不对;
发现反汇编出来的伪代码也有点奇奇怪怪的;在这里插入图片描述
可以发现有上下左右四个方向,并且碰到1退出,碰到#输出flag,应该是一个迷宫,再查看01串长度正好25;

在这里插入图片描述
得到222441144222

flag{222441144222}

10.SimpleRev

首先就是一个普普通通的64位文件,简单题就不看有没有加壳了,大概率是没有的。
老样子拖进IDA看看情况。
在这里插入图片描述

这个伪代码一看就不简单。
关键就在于Dercy()这个函数,点进去看一下。

 v12 = *MK_FP(__FS__, 40LL);
  *(_QWORD *)src = 'SLCDN';					//NDCLS
  v7 = 0LL;
  v8 = 0;
  v9 = 'wodah';								//hadow
  v10 = 0LL;
  v11 = 0;
  text = join(key3, (const char *)&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] > '@' && key[v3 % v5] <= 'Z' )
      key[i] = key[v3 % v5] + 32;
    ++v3;
  }
  printf("Please input your flag:", src);
  while ( 1 )
  {
    v1 = getchar();
    if ( v1 == '\n' )
      break;
    if ( v1 == ' ' )
    {
      ++v2;
    }
    else
    {
      if ( v1 <= 96 || v1 > 122 )
      {
        if ( v1 > '@' && v1 <= 'Z' )
          str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
      }
      else
      {
        str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
      }
      if ( !(v3 % v5) )
        putchar(32);
      ++v2;
    }
  }
  if ( !strcmp(text, str2) )
    puts("Congratulation!\n");
  else
    puts("Try again!\n");
  return *MK_FP(__FS__, 40LL) ^ v12;
}

在这里插入图片描述

将src和v9的值换成十六进制,可以到这两个是大端序,但是数据在内存中都是小端序,所以我们要将其转一下,一般在CPU,x86都是小端序,但是IDA将其转换为大端序。(具体如何判断我也不是很清楚,查了很多也没有一个所以然,大家就先这样记忆吧)
src = NDCLS, v9 = hadow;
join连接key3和v9,key3点进去得到kills,所以text = killshadow。
strcpy(key, key1); //复制函数,将key1的字符串复制给key。
key1点进去得到ADSFK。
strcat函数,是将key 和 src 拼接在一起的函数, 所以key = ADSFKNDCLS。
在这里插入图片描述
这个key[v3%v5]是大写字母,则把它变为小写字母。大小写字母的ASCII码,相差32。
在这里插入图片描述
看到最下面的if语句,如果!strcmp(text ,str2),则正确,strcmp函数,是比较函数,如果两个字符串相同,则等于0,所以text = str2才成功。

而得到str2的关键就是:
str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97

接下来,写脚本。

lt='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
key=list('ADSFKNDCLS'.lower())
klens=len(key)

text='killshadow'
flag=''
for i in range(len(text)):
    str2=text[i]
    for c in lt:
        if str2== chr((ord(c) - 39 - ord(key[i  % klens]) + 97) % 26 + 97):
            flag+=c
print('flag{'+flag+'}')

lt可以试试大写也可以试试小写,这里我个人不确定是大写还是小写,不过大写答案正确

flag{KLDQCUDFZO}

11.Java逆向解密

文件下载完成后打开是.class文件。
在这里插入图片描述
.class文件是.java文件编译后生成的字节码文件,我们使用一般的文本编辑工具打开的话,里面的内容是乱码。 使用专业的集成开发工具(IDE)可以打开.class文件,如eclipse,idea等。

下载了打开反汇编Java的工具
在这里插入图片描述
逻辑清晰简单,就是我们输入一个字符串
然后经过一个for循环进行异或
然后将得到的新字符串与KEY进行比较,看看是否相等。

解码的python脚本如下

str = [180, 136, 137, 147, 191, 137, 147, 191, 148, 
       136, 133, 191, 134, 140, 129, 135, 191, 65 ]

flag=' '

for i in range(len(str)):
    flag+=chr(str[i]-ord('@')^0x20)
print(flag)

得到flag为

flag{ This_is_the_flag_!}

12.刮开有奖

首先还是例行检查,看看有没有壳。
在这里插入图片描述
正常的文件,没有加壳。

然后我试了试x64dbg,不过并没有什么用处。

用IDA试了试,看到了DialogFunc函数,反汇编得到伪代码。

BOOL __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
{
  const char *v4; // esi@5
  const char *v5; // edi@5
  BOOL result; // eax@14
  int v7; // [sp+8h] [bp-20030h]@5
  int v8; // [sp+Ch] [bp-2002Ch]@5
  int v9; // [sp+10h] [bp-20028h]@5
  int v10; // [sp+14h] [bp-20024h]@5
  int v11; // [sp+18h] [bp-20020h]@5
  int v12; // [sp+1Ch] [bp-2001Ch]@5
  int v13; // [sp+20h] [bp-20018h]@5
  int v14; // [sp+24h] [bp-20014h]@5
  int v15; // [sp+28h] [bp-20010h]@5
  int v16; // [sp+2Ch] [bp-2000Ch]@5
  int v17; // [sp+30h] [bp-20008h]@5
  CHAR String; // [sp+34h] [bp-20004h]@4
  char v19; // [sp+35h] [bp-20003h]@6
  char v20; // [sp+36h] [bp-20002h]@5
  char v21; // [sp+37h] [bp-20001h]@5
  char v22; // [sp+38h] [bp-20000h]@5
  char v23; // [sp+39h] [bp-1FFFFh]@5
  char v24; // [sp+3Ah] [bp-1FFFEh]@5
  char v25; // [sp+3Bh] [bp-1FFFDh]@5
  char v26; // [sp+10034h] [bp-10004h]@5
  char v27; // [sp+10035h] [bp-10003h]@5
  char v28; // [sp+10036h] [bp-10002h]@5

  if ( a2 == 272 )
  {
    result = 1;
  }
  else
  {
    if ( a2 != 273 )
      return 0;
    if ( (_WORD)a3 == 1001 )
    {
      memset(&String, 0, 0xFFFFu);
      GetDlgItemTextA(hDlg, 1000, &String, 0xFFFF);
      if ( strlen(&String) == 8 )
      {
        v7 = 'Z';
        v8 = 'J';
        v9 = 'S';
        v10 = 'E';
        v11 = 'C';
        v12 = 'a';
        v13 = 'N';
        v14 = 'H';
        v15 = '3';
        v16 = 'n';
        v17 = 'g';
        sub_4010F0((int)&v7, 0, 10);
        memset(&v26, 0, 65535u);
        v26 = v23;
        v28 = v25;
        v27 = v24;
        v4 = (const char *)sub_401000((int)&v26, strlen(&v26));
        memset(&v26, 0, 0xFFFFu);
        v27 = v21;
        v26 = v20;
        v28 = v22;
        v5 = (const char *)sub_401000((int)&v26, strlen(&v26));
        if ( String == v7 + 34
          && v19 == v11
          && 4 * v20 - 141 == 3 * v9
          && v21 / 4 == 2 * (v14 / 9)
          && !strcmp(v4, "ak1w")
          && !strcmp(v5, "V1Ax") )
          MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
      }
      return 0;
    }
    if ( (_WORD)a3 != 1 && (_WORD)a3 != 2 )
      return 0;
    EndDialog(hDlg, (unsigned __int16)a3);
    result = 1;
  }
  return result;
}

大概可以看出我们的flag是8位长度的字符串。
在这里插入图片描述
看伪代码分析太麻烦了,所以转成C语言代码运行一下。记得把*(_DWORD*) 删掉,因为这是汇编的表示,然后将各种基址+偏移的表示也换成数组的寻址,如下

#include <stdio.h>
#include <string.h>

int sub_4010F0(char*a1,int a2,int a3)
{
	int result;
	int i;
	int v5;
	int v6;
	
	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(void)
{
	char str[]="ZJSECaNH3ng";
	sub_4010F0(str,0,10);
	printf("%s",str);
	return 0;
}

得到结果为3CEHJNSZagn

分析代码,转到汇编处。
在这里插入图片描述
看加粗加红处(下面是对应字符串的信息)在这里插入图片描述
我们可以知道,v6使用sub_4010F0函数后的字符串的6,7,8位,调用sub_401000函数,v7使用sub_4010F0函数后的字符串的3,4,5位,调用sub_401000函数。(这一步我自己其实一直不能理解。)

然后进入sub_401000,观察里面的加密方式。

void *__cdecl sub_401000(int a1, signed int a2)
{
  int v2; // eax@1
  signed int v3; // esi@1
  size_t v4; // ebx@3
  void *v5; // eax@3
  void *v6; // edi@3
  signed int v7; // eax@5
  void *v8; // ebx@5
  int v9; // edi@8
  signed int v10; // edx@8
  signed int v11; // edi@11
  signed int v12; // eax@11
  signed int v13; // esi@11
  void *result; // eax@18
  void *v15; // [sp+Ch] [bp-10h]@3
  void *v16; // [sp+10h] [bp-Ch]@5
  signed int v17; // [sp+14h] [bp-8h]@11
  int v18; // [sp+18h] [bp-4h]@8

  v2 = a2 / 3;
  v3 = 0;
  if ( a2 % 3 > 0 )
    ++v2;
  v4 = 4 * v2 + 1;
  v5 = malloc(v4);
  v6 = v5;
  v15 = v5;
  if ( !v5 )
    exit(0);
  memset(v5, 0, v4);
  v7 = a2;
  v8 = v6;
  v16 = v6;
  if ( a2 > 0 )
  {
    while ( 1 )
    {
      v9 = 0;
      v10 = 0;
      v18 = 0;
      do
      {
        if ( v3 >= v7 )
          break;
        ++v10;
        v9 = *(_BYTE *)(v3++ + a1) | (v9 << 8);
      }
      while ( v10 < 3 );
      v11 = v9 << 8 * (3 - v10);
      v12 = 0;
      v17 = v3;
      v13 = 18;
      do
      {
        if ( v10 >= v12 )
        {
          *((_BYTE *)&v18 + v12) = (v11 >> v13) & 0x3F;
          v8 = v16;
        }
        else
        {
          *((_BYTE *)&v18 + v12) = 64;
        }
        *(_BYTE *)v8 = byte_407830[*((_BYTE *)&v18 + v12)];
        v8 = (char *)v8 + 1;
        v13 -= 6;
        ++v12;
        v16 = v8;
      }
      while ( v13 > -6 );
      v3 = v17;
      if ( v17 >= a2 )
        break;
      v7 = a2;
    }
    v6 = v15;
  }
  result = v6;
  *(_BYTE *)v8 = 0;
  return result;
}

又是一个很复杂的代码,然后我们看到函数byte_407830,点进去看到
在这里插入图片描述
一看也知道是base64加密。

      if ( String == v9 + 34                // sub_4010F0函数后的第一位等于51+34=85-->'U'
        && v21 == v13                       // 第2位,等于v13,即sub_4010F0函数返回值的第5位值-->'J'
        && 4 * v22 - 141 == 3 * v11
        && v23 / 4 == 2 * (v16 / 9)
        && !strcmp(v6, "ak1w")              // 第6,7,8行代码base64之后,需要等于"ak1w"
        && !strcmp(                         // 第3,4,5行代码,加密之后等于V1Ax
              v7,
              "V1Ax") )
      {
        MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
      }

最后得到flag为

flag{UJWP1jMp}

13.rsa

首先看到这道题目的时候真的是一头雾水,不知道给的文件是用来干什么的;
在这里插入图片描述
然后就去搜索enc文件,想着可以把它转换成代码,然后去分析代码,果然这条路没有走通,然后就在网上看到别人介绍RsaCtfTool这个工具,下载了好久才下载完成;

看这篇文章,来下载RsaCtfTool;
安装RsaCtfTool

然后把文件复制到Kali中,使用命令

python3 RsaCtfTool.py --publickey pub.key --uncipherfile flag.enc

得到flag
在这里插入图片描述
所以flag为

flag{decrypt_256}

14.findit

文件下载好了,.apk文件,安卓逆向。
用apk改之理看一看
在这里插入图片描述
找到主函数。
打开后看到一串十六进制数。
在这里插入图片描述
转换成字符的形式。

str=[0x70,0x76,0x6B,0x71,0x7b,0x6d,0x31,0x36,0x34,0x36,0x37,0x35,0x32,0x36,0x32,0x30,0x33,0x33,0x6c,
0x34,0x6d,0x34,0x39,0x6c,0x6e,0x70,0x37,0x70,0x39,0x6d,0x6e,0x6b,0x32,0x38,0x6b,0x37,0x35,0x7d]

flag=''
for i in range(0,len(str)):
    flag+=chr(str[i])
print(flag)

得到一串字符

pvkq{m164675262033l4m49lnp7p9mnk28k75}

以为这就是flag,提交后发现不对,仔细观察后感觉像是凯撒密码
解密一下得到
在这里插入图片描述

flag{c164675262033b4c49bdf7f9cda28a75}

15.简单注册器

文件下载好后是一个.apk文件,安卓逆向。
用Jadx-gui反编译,得到主要代码。
在这里插入图片描述
然后写脚本把flag跑出来

flagtrue = "dd2940c04462b4dd7c450528835cca15"
x = [i for i in flagtrue]
x[2] = chr(ord(x[2]) + ord(x[3]) - 0x32)
x[4] = chr(ord(x[2]) + ord(x[5]) - 0x30)
x[0x1e] = chr(ord(x[0x1f]) + ord(x[0x9]) - 0x30)
x[0xe] = chr(ord(x[0x1b]) + ord(x[0x1c]) - 0x61)

for i in range(16):
    x[i],x[31-i] = x[31-i],x[i]

print ("flag{"+ ''.join(x) + "}")

这是别人写的脚本,python没学好,我自己手算的,这么简单都不会,还不赶紧学python。

得到flag为:

flag{59acc538825054c7de4b26440c0999dd}

16.[BJDCTF2020]JustRE

还是先检查一下有没有壳
在这里插入图片描述
没有加壳。
拖到IDA里面看一看。
找到一个比较关键的字符
在这里插入图片描述
找到关键函数,反编译一下
在这里插入图片描述
输出了aBjdDD2069a4579,19999,0,aBjdDD2069a4579是BJD{%d%d2069a45792d233ac},19999和0填入到里面的%d位置,得到flag

flag{1999902069a45792d233ac}

17.[GWCTF 2019]pyre

看到名字的时候就猜到肯定和python有关。
下载文件,果不其然.pyc文件(python代码转换为字节码后的文件)
用python反编译工具:python反编译

打开后得到
在这里插入图片描述
轻轻松松反编译出来
结果我自己数学不好,python写的又烂,还是看了别人的wp才写出来的;
关于异或,我们要知道这样一个技巧:
a ^ 0=a,a ^ a=0,那么可得:a ^ b ^ a=b,a ^ b ^ b = a;
由code[i]=code[i] ^ code[i+1],i从0取到l-1-1。处理后,code[l-1]没有变,那么要逆向,则令x从l-2取到0,使code[x]=code[x] ^ code[x+1](a ^ b ^ b = a) 。
关于取模,(a%c+b%c)=(a+b)%c,所以num等价于(input[i] +i)%128

解密脚本:

code = ['\x1f','\x12','\x1d','(','0','4','\x01','\x06','\x14','4',
        ',','\x1b','U','?','o','6','*',':','\x01','D',';','%','\x13']

l=len(code)
flag=' '
for i in range(l-2,-1,-1):
    code[i]=chr(ord(code[i])^ord(code[i+1]))

for i in range(len(code)):
    flag+=chr((ord(code[i])-i)%128)

print(flag)

得到flag为GWHT{Just_Re_1s_Ha66y!}

flag{Just_Re_1s_Ha66y!}

18.[GXYCTF2019]luck_guy

再写这题的时候已经是时隔一年了,没想过会再来搞逆向,不过来都来了,就做下吧

可以看到是64位文件,没有加壳
在这里插入图片描述
拖进IDA里面去看一下,先看main()函数
在这里插入图片描述
我们先会进入welcome()函数,点击welcome()函数看一下,啥也没有,回去看看函数patch_me()
在这里插入图片描述
看一下函数patch_me(),发现如果输入的数是偶数,就可以进入函数get_flag()
在这里插入图片描述
我们进入get_flag()看一下,可以看出来这就是我们需要分析代码的地方
在这里插入图片描述
读到这段代码的时候,就感觉有点奇怪,好像代码不是连续的,逻辑上就有点奇奇怪怪的

后来看了一些大佬的讲解,才知道代码给我这样感觉的原因。因为这里的switch-case是随机的,所以可以不用管。

我们可以发现case1就是flag,flag是由f1和f2拼接得到的,而f1是固定的,只需要看f2就可以了。
在这里插入图片描述
我们可以看到case4中f2进行了定义,case5中对f2进行了处理
所以我们的顺序是4->5->1

我们上脚本,其实我一直不太理解这里的小端序大端序的问题,自己也没找到一些文章能帮助理解的

f2 = [0x69, 0x63, 0x75, 0x67, 0x60, 0x6f, 0x66, 0x7f]	#小端序的问题,所以要逆序一下
flag = 'GXY{do_not_'

for j in range(8):
    if (j % 2 == 1):
        flag += chr(f2[j] - 2)
    else:
        flag += chr(f2[j] - 1)

print(flag)

19.[ACTF新生赛2020]easyre

还是先查查壳。
在这里插入图片描述
有壳,upx,拖到Linux里面去脱壳。
在这里插入图片描述
脱壳后的文件拖到IDA里面反编译一下,点击main()。
得到的伪代码
在这里插入图片描述
代码还算简单,但是我自己理解能力太差,看了好久还是没怎么看明白。
着眼观察for循环就行,从for循环了解到flag长度应该是12,
*(&v4 + i) !=data_start_[ *( ( char *)&v16 + i ) - 1] ) 的意思是在_data_start__字符串里面寻找一个字符然后 -1 与v4进行对比,注意括号的位置就能知道 -1 是减到索引还是索引值上,所以逆过来就是 +1。
在这里插入图片描述
python脚本

key = '~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)(\'&%$# !"' #'一定要加\
encrypt = [42,70,39,34,78,44,34,40,73,63,43,64]
x = []
flag = ''
for i in encrypt:
  x.append(key.find(chr(i))+1) 
for i in x:
  flag += chr(i)
print(flag)

借鉴一下别人的脚本,自己写的错误百出。
最后flag为:

flag{U9X_1S_W6@T?}

20.CrackRTF

首先还是看看有没有加壳;
在这里插入图片描述
没有加壳,继续分析,拖到IDA里面看看。
这个代码真的是看的我头疼
在这里插入图片描述
自己看了好久也没有进展,看了几位大佬的wp;

if ( strlen((const char *)&pbData) != 6 )
  {
    printf("Must be 6 characters!\n");
    ExitProcess(0);
  }
  v5 = unknown_libname_1((char *)&pbData);
  if ( v5 < 100000 )

从这里可以看出我们的密码是六位的,点击unknown_libname_1函数,得到的是下图的函数
在这里插入图片描述
atol函数:用来将字符串转换成长整型数 ,并且转化后的整型要大于100000;

strcat((char *)&pbData, "@DBApp");
v0 = strlen((const char *)&pbData);

这个代码,第一行将 “ @DBApp ” 连接到密码的后面,第二行求出连接之后的密码为12;

sub_40100A(&pbData, v0, &String1)

sub_40100A是一个加密函数

memset(&v4, 0xCCu, 0x68u);
  if ( CryptAcquireContextA(&phProv, 0, 0, 1u, 0xF0000000) )
  {
    if ( CryptCreateHash(phProv, 0x8004u, 0, 0, &phHash) )
    {
      if ( CryptHashData(phHash, pbData, dwDataLen, 0) )
      {
        CryptGetHashParam(phHash, 2u, v7, &pdwDataLen, 0);
        *lpString1 = 0;
        for ( i = 0; i < pdwDataLen; ++i )
        {
          wsprintfA(&String2, "%02X", v7[i]);
          lstrcatA(lpString1, &String2);
        }
        CryptDestroyHash(phHash);
        CryptReleaseContext(phProv, 0);
        result = 1;
      }
      else
      {
        CryptDestroyHash(phHash);
        CryptReleaseContext(phProv, 0);
        result = 0;
      }
    }
    else
    {
      CryptReleaseContext(phProv, 0);
      result = 0;
    }
  }
  else
  {
    result = 0;
  }
  return result;
}

这加密函数看着就头疼;

 CryptCreateHash(phProv, 0x8004u, 0, 0, &phHash)

搜索过后发现这个是哈希函数。

代码中的0x8004是标识符,并且是SHA1的算法
在这里插入图片描述
然后自己查了一下hashlib模块使用的方法
里面的16进制str类型的消息摘要,都是小写的英文字母
参考一下别人写的的代码
爆破代码如下:

import hashlib
string='@DBApp'
for i in range(100000,999999):
    flag=str(i)+string
    x = hashlib.sha1(flag.encode("utf8"))
    y = x.hexdigest()
    if "6e32d0943418c2c33385bc35a1470250dd8923a9" == y:
            print(flag)
            break

得到密码为:123321@DBApp
所以我们知道前六位密码是123321

一些代码的讲解:
str通过encode()转换为bytes(二进制)
在python3中,encode()和decode()默认使用UTF-8
x.hexdigest()函数表示获得16进制str类型的消息摘要

第二部分和第一部分相类似,但是没有给我们范围,没办法爆破,只能自己慢慢看函数;
进入函数看到0x8003u,是MD5加密,但是解不出来;
在这里插入图片描述
再进入加密函数看一下
在这里插入图片描述
就没有正常一点的函数吗???

这一段代码的含义就是,从AAA文件中查找字符,然后如果没有找到就返回,找到了的话就计算出资源的大小,把资源第一个字符出的指针传给lpBuffer
这里我们可以用一个叫做ResourceHacker的工具来查看资源
在这里插入图片描述
但是还是看不懂;

往里面看看还有异或的函数:
在这里插入图片描述
a2就是AAA中得到的首部指针,v5是字符串的长度,也就是密码的长度。
整理一下,在进行异或完之后会生成一个RTF文件;
这个时候我们不妨打开一个RTF文件来查看它的头部
在这里插入图片描述
得到前六位是{\rtf1
再看资源的前六位是
在这里插入图片描述
资源的每一位和密码的每一位循环异或
异或结束之后,生成一个rtf文件
接下来这一步是我觉得很骚气 巧妙的一步
思考一下
我们的密码一共是6+12=18位
我们现在想要的是前六位的密码,循环异或的话,那么也就是说,资源的前六位与密码的前六位异或的结果就是rtf文件的前六位
这里的思想是借鉴的别人的

下面的脚本是借鉴别人的;

rtf = '{\\rtf1' \\需要注意,\r需要转义,变成\\r
A = [0x05, 0x7D, 0x41, 0x15, 0x26, 0x01]
password=''
for i in range(len(rtf)):
    x = ord(rtf[i]) ^ A[i]
    password+=chr(x)
print(password)

得到的结果为~!3a@0
第二段的密码为~!3a@0123321@DBApp
两端密码输入完后,就会在程序所在文件夹中生成一个带有flag的rtf文件,打开就能得到flag
flag为Flag{N0_M0re_Free_Bugs}

flag{N0_M0re_Free_Bugs}

21.[ACTF新生赛2020]rome

首先我们拖进虚拟机中,可以看到是32位文件
在这里插入图片描述
然后我们再放到IDA里面看看,找到伪代码

int func()
{
  int result; // eax
  int v1; // [esp+14h] [ebp-44h]
  int v2; // [esp+18h] [ebp-40h]
  int v3; // [esp+1Ch] [ebp-3Ch]
  int v4; // [esp+20h] [ebp-38h]
  unsigned __int8 v5; // [esp+24h] [ebp-34h]
  unsigned __int8 v6; // [esp+25h] [ebp-33h]
  unsigned __int8 v7; // [esp+26h] [ebp-32h]
  unsigned __int8 v8; // [esp+27h] [ebp-31h]
  unsigned __int8 v9; // [esp+28h] [ebp-30h]
  int v10; // [esp+29h] [ebp-2Fh]
  int v11; // [esp+2Dh] [ebp-2Bh]
  int v12; // [esp+31h] [ebp-27h]
  int v13; // [esp+35h] [ebp-23h]
  unsigned __int8 v14; // [esp+39h] [ebp-1Fh]
  char v15; // [esp+3Bh] [ebp-1Dh]
  char v16; // [esp+3Ch] [ebp-1Ch]
  char v17; // [esp+3Dh] [ebp-1Bh]
  char v18; // [esp+3Eh] [ebp-1Ah]
  char v19; // [esp+3Fh] [ebp-19h]
  char v20; // [esp+40h] [ebp-18h]
  char v21; // [esp+41h] [ebp-17h]
  char v22; // [esp+42h] [ebp-16h]
  char v23; // [esp+43h] [ebp-15h]
  char v24; // [esp+44h] [ebp-14h]
  char v25; // [esp+45h] [ebp-13h]
  char v26; // [esp+46h] [ebp-12h]
  char v27; // [esp+47h] [ebp-11h]
  char v28; // [esp+48h] [ebp-10h]
  char v29; // [esp+49h] [ebp-Fh]
  char v30; // [esp+4Ah] [ebp-Eh]
  char v31; // [esp+4Bh] [ebp-Dh]
  int i; // [esp+4Ch] [ebp-Ch]

  v15 = 'Q';
  v16 = 's';
  v17 = 'w';
  v18 = 51;
  v19 = 115;
  v20 = 106;
  v21 = 95;
  v22 = 108;
  v23 = 122;
  v24 = 52;
  v25 = 95;
  v26 = 85;
  v27 = 106;
  v28 = 119;
  v29 = 64;
  v30 = 108;
  v31 = 0;
  printf("Please input:");
  scanf("%s", &v5);
  result = v5;
  if ( v5 == 'A' )
  {
    result = v6;
    if ( v6 == 'C' )
    {
      result = v7;
      if ( v7 == 'T' )
      {
        result = v8;
        if ( v8 == 'F' )
        {
          result = v9;
          if ( v9 == '{' )
          {
            result = v14;
            if ( v14 == '}' )
            {
              v1 = v10;
              v2 = v11;
              v3 = v12;
              v4 = v13;
              for ( i = 0; i <= 15; ++i )
              {
                if ( *((_BYTE *)&v1 + i) > 64 && *((_BYTE *)&v1 + i) <= 90 )
                  *((_BYTE *)&v1 + i) = (*((char *)&v1 + i) - 51) % 26 + 65;
                if ( *((_BYTE *)&v1 + i) > 96 && *((_BYTE *)&v1 + i) <= 122 )
                  *((_BYTE *)&v1 + i) = (*((char *)&v1 + i) - 79) % 26 + 97;
              }
              for ( i = 0; i <= 15; ++i )
              {
                result = (unsigned __int8)*(&v15 + i);
                if ( *((_BYTE *)&v1 + i) != (_BYTE)result )
                  return result;
              }
              result = printf("You are correct!");
            }
          }
        }
      }
    }
  }
  return result;
}

凯撒加密+大小写互换,程序的意思就是,让我们输入一个字符串,然后判断大小写,进行相应的运算,最后得到了程序开头的数组

v15 = ['Q','s','w','3','s','j', '_','l','z','4','_','U','j','w','@','l']

看一下主要的运算代码

for ( i = 0; i <= 15; ++i )
              {
                if ( *((_BYTE *)&v1 + i) > 64 && *((_BYTE *)&v1 + i) <= 90 )
                  *((_BYTE *)&v1 + i) = (*((char *)&v1 + i) - 51) % 26 + 65;
                if ( *((_BYTE *)&v1 + i) > 96 && *((_BYTE *)&v1 + i) <= 122 )
                  *((_BYTE *)&v1 + i) = (*((char *)&v1 + i) - 79) % 26 + 97;
              }
              for ( i = 0; i <= 15; ++i )
              {
                result = (unsigned __int8)*(&v15 + i);
                if ( *((_BYTE *)&v1 + i) != (_BYTE)result )
                  return result;
              }

我们这里用暴力破解

v15= [ 'Q','s','w','3','s','j', '_','l','z','4','_','U','j','w','@','l' ]
flag = ' '

for i in range(16):
    for j in range(128):	#ascii表上有127个字符
        x=j
        if chr(x).isupper():
            x=(x-51)%26+65
        if chr(x).islower():
            x=(x-79)%26 +97
        if chr(x) == v15[i]:
            flag+=chr(j)
print('flag{'+flag+'}')

22.[FlareOn4]login

多多少少有点离谱的简单题,下载好附件,是一个网页,F12可以看到有一个类似于算法和密文的东西
在这里插入图片描述
我自己一开始的想法还是,就是看看能不能读懂这个类似算法的东西,但是看了半天发现无从下手。
但是我们仔细读代码,可以发现里面有一个rot,让我一下子联想到ROT13加密解密
然后我就直接在线找了一个网站,加密解密,就成功了,解密出来的就是flag
在这里插入图片描述

23.[2019红帽杯]easyRE

是64位程序并且没有加壳的
在这里插入图片描述
老样子拖进IDA看一下,打开字符串,看到有一些关键字
在这里插入图片描述
"x"键交叉引用,切换到关键代码
在这里插入图片描述
看一下切换到的代码

signed __int64 sub_4009C6()
{
  char *v0; // rsi
  char *v1; // rdi
  signed __int64 result; // rax
  __int64 v3; // ST10_8
  __int64 v4; // ST18_8
  __int64 v5; // ST20_8
  __int64 v6; // ST28_8
  __int64 v7; // ST30_8
  __int64 v8; // ST38_8
  __int64 v9; // ST40_8
  __int64 v10; // ST48_8
  __int64 v11; // ST50_8
  __int64 v12; // ST58_8
  int i; // [rsp+Ch] [rbp-114h]
  char v14; // [rsp+60h] [rbp-C0h]
  char v15; // [rsp+61h] [rbp-BFh]
  char v16; // [rsp+62h] [rbp-BEh]
  char v17; // [rsp+63h] [rbp-BDh]
  char v18; // [rsp+64h] [rbp-BCh]
  char v19; // [rsp+65h] [rbp-BBh]
  char v20; // [rsp+66h] [rbp-BAh]
  char v21; // [rsp+67h] [rbp-B9h]
  char v22; // [rsp+68h] [rbp-B8h]
  char v23; // [rsp+69h] [rbp-B7h]
  char v24; // [rsp+6Ah] [rbp-B6h]
  char v25; // [rsp+6Bh] [rbp-B5h]
  char v26; // [rsp+6Ch] [rbp-B4h]
  char v27; // [rsp+6Dh] [rbp-B3h]
  char v28; // [rsp+6Eh] [rbp-B2h]
  char v29; // [rsp+6Fh] [rbp-B1h]
  char v30; // [rsp+70h] [rbp-B0h]
  char v31; // [rsp+71h] [rbp-AFh]
  char v32; // [rsp+72h] [rbp-AEh]
  char v33; // [rsp+73h] [rbp-ADh]
  char v34; // [rsp+74h] [rbp-ACh]
  char v35; // [rsp+75h] [rbp-ABh]
  char v36; // [rsp+76h] [rbp-AAh]
  char v37; // [rsp+77h] [rbp-A9h]
  char v38; // [rsp+78h] [rbp-A8h]
  char v39; // [rsp+79h] [rbp-A7h]
  char v40; // [rsp+7Ah] [rbp-A6h]
  char v41; // [rsp+7Bh] [rbp-A5h]
  char v42; // [rsp+7Ch] [rbp-A4h]
  char v43; // [rsp+7Dh] [rbp-A3h]
  char v44; // [rsp+7Eh] [rbp-A2h]
  char v45; // [rsp+7Fh] [rbp-A1h]
  char v46; // [rsp+80h] [rbp-A0h]
  char v47; // [rsp+81h] [rbp-9Fh]
  char v48; // [rsp+82h] [rbp-9Eh]
  char v49; // [rsp+83h] [rbp-9Dh]
  char v50[32]; // [rsp+90h] [rbp-90h]
  int v51; // [rsp+B0h] [rbp-70h]
  char v52; // [rsp+B4h] [rbp-6Ch]
  char v53; // [rsp+C0h] [rbp-60h]
  char v54; // [rsp+E7h] [rbp-39h]
  char v55; // [rsp+100h] [rbp-20h]
  unsigned __int64 v56; // [rsp+108h] [rbp-18h]

  v56 = __readfsqword(0x28u);
  v14 = 73;
  v15 = 111;
  v16 = 100;
  v17 = 108;
  v18 = 62;
  v19 = 81;
  v20 = 110;
  v21 = 98;
  v22 = 40;
  v23 = 111;
  v24 = 99;
  v25 = 121;
  v26 = 127;
  v27 = 121;
  v28 = 46;
  v29 = 105;
  v30 = 127;
  v31 = 100;
  v32 = 96;
  v33 = 51;
  v34 = 119;
  v35 = 125;
  v36 = 119;
  v37 = 101;
  v38 = 107;
  v39 = 57;
  v40 = 123;
  v41 = 105;
  v42 = 121;
  v43 = 61;
  v44 = 126;
  v45 = 121;
  v46 = 76;
  v47 = 64;
  v48 = 69;
  v49 = 67;
  memset(v50, 0, sizeof(v50));
  v51 = 0;
  v52 = 0;
  v0 = v50;
  sub_4406E0(0LL, v50, 37LL);
  v52 = 0;
  v1 = v50;
  if ( sub_424BA0(v50) == 36 )
  {
    for ( i = 0; ; ++i )
    {
      v1 = v50;
      if ( i >= (unsigned __int64)sub_424BA0(v50) )
        break;
      if ( (unsigned __int8)(v50[i] ^ i) != *(&v14 + i) )
      {
        result = 4294967294LL;
        goto LABEL_13;
      }
    }
    sub_410CC0("continue!");
    memset(&v53, 0, 0x40uLL);
    v55 = 0;
    v0 = &v53;
    sub_4406E0(0LL, &v53, 64LL);
    v54 = 0;
    v1 = &v53;
    if ( sub_424BA0(&v53) == 39 )
    {
      v3 = sub_400E44((__int64)&v53);
      v4 = sub_400E44(v3);
      v5 = sub_400E44(v4);
      v6 = sub_400E44(v5);
      v7 = sub_400E44(v6);
      v8 = sub_400E44(v7);
      v9 = sub_400E44(v8);
      v10 = sub_400E44(v9);
      v11 = sub_400E44(v10);
      v12 = sub_400E44(v11);
      v0 = off_6CC090;
      v1 = (char *)v12;
      if ( !(unsigned int)sub_400360(v12, off_6CC090) )
      {
        sub_410CC0("You found me!!!");
        v1 = "bye bye~";
        sub_410CC0("bye bye~");
      }
      result = 0LL;
    }
    else
    {
      result = 4294967293LL;
    }
  }
  else
  {
    result = 0xFFFFFFFFLL;
  }
LABEL_13:
  if ( __readfsqword(0x28u) != v56 )
    sub_444020(v1, v0);
  return result;
}

先分析v50有关的代码,将用户输入与i异或后与在栈上存的数据进行比对
写脚本

v50 = [0x49,0x6F,0x64,0x6C,0x3E,0x51,0x6E,0x62,0x28,0x6F,0x63,0x79,0x7F,0x79,0x2E,0x69,0x7F,0x64,0x60,0x33,0x77,0x7D,0x77,0x65,0x6B,0x39,0x7B,0x69,0x79,0x3D,0x7E,0x79,0x4C,0x40,0x45,0x43]
flag=' '

for i in range(len(v50)):
    flag+=chr(v50[i]^i)
print(flag)

得到提示
在这里插入图片描述
然后我们接着看下半部分的代码
在这里插入图片描述
我们进入函数sub_400E44()看一下,经过观察我们可以看出来这是base64编码
在这里插入图片描述
我们找到编码过后的密文
在这里插入图片描述
找在线网站解码,给了我一个网址
在这里插入图片描述
毫无疑问的我们被骗了,啥也没有,这不是关键代码,这是障眼法
在这里插入图片描述
在第二次输入加密后对比的常量下面,还发现了一个常量,在sub_400D35函数中调用
在这里插入图片描述
交叉引用,看一下伪代码
在这里插入图片描述
仔细读这段代码,v5先与byte_6CC0A0这个数组的前四个值异或,然后在与v8异或得出flag,v5=v8,所以我们先求解v5
我们看一下数组byte_6CC0A0
在这里插入图片描述
写脚本

data1 = [0x66,0x6c,0x61,0x67]
data2 = [0x40,0x35,0x20,0x56]
data3 = [0x40,0x35,0x20,0x56,0x5D,0x18,0x22,0x45,0x17,0x2F,0x24,0x6E,0x62,0x3C,
		 0x27,0x54,0x48,0x6C,0x24,0x6E,0x72,0x3C,0x32,0x45,0x5B]
v5='&YA1'
v8=[0x26,0x59,0x41,0x31]
flag=' '

for i in range(4):
    v5 += chr(data1[i]^data2[i])
print(v5)

for i in range(25):
    flag += chr(data3[i]^v8[i%4])
print(flag)

运行后得出flag
在这里插入图片描述

24.[GUET-CTF2019]re

查壳工具看一下,发现有壳,是upx的
在这里插入图片描述
拖进kali里面脱壳
在这里插入图片描述
查一下可以看到是64位程序
在这里插入图片描述
我们再拖进IDA里面看一下,找到伪代码
在这里插入图片描述
观察代码可以发现,关键就是在sub_4009AE()这个函数上,点进去看一下

_BOOL8 __fastcall sub_4009AE(char *a1)
{
  if ( 1629056 * *a1 != 166163712 )
    return 0LL;
  if ( 6771600 * a1[1] != 731332800 )
    return 0LL;
  if ( 3682944 * a1[2] != 357245568 )
    return 0LL;
  if ( 10431000 * a1[3] != 1074393000 )
    return 0LL;
  if ( 3977328 * a1[4] != 489211344 )
    return 0LL;
  if ( 5138336 * a1[5] != 518971936 )
    return 0LL;
  if ( 7532250 * a1[7] != 406741500 )
    return 0LL;
  if ( 5551632 * a1[8] != 294236496 )
    return 0LL;
  if ( 3409728 * a1[9] != 177305856 )
    return 0LL;
  if ( 13013670 * a1[10] != 650683500 )
    return 0LL;
  if ( 6088797 * a1[11] != 298351053 )
    return 0LL;
  if ( 7884663 * a1[12] != 386348487 )
    return 0LL;
  if ( 8944053 * a1[13] != 438258597 )
    return 0LL;
  if ( 5198490 * a1[14] != 249527520 )
    return 0LL;
  if ( 4544518 * a1[15] != 445362764 )
    return 0LL;
  if ( 3645600 * a1[17] != 174988800 )
    return 0LL;
  if ( 10115280 * a1[16] != 981182160 )
    return 0LL;
  if ( 9667504 * a1[18] != 493042704 )
    return 0LL;
  if ( 5364450 * a1[19] != 257493600 )
    return 0LL;
  if ( 13464540 * a1[20] != 767478780 )
    return 0LL;
  if ( 5488432 * a1[21] != 312840624 )
    return 0LL;
  if ( 14479500 * a1[22] != 1404511500 )
    return 0LL;
  if ( 6451830 * a1[23] != 316139670 )
    return 0LL;
  if ( 6252576 * a1[24] != 619005024 )
    return 0LL;
  if ( 7763364 * a1[25] != 372641472 )
    return 0LL;
  if ( 7327320 * a1[26] != 373693320 )
    return 0LL;
  if ( 8741520 * a1[27] != 498266640 )
    return 0LL;
  if ( 8871876 * a1[28] != 452465676 )
    return 0LL;
  if ( 4086720 * a1[29] != 208422720 )
    return 0LL;
  if ( 9374400 * a1[30] == 515592000 )
    return 5759124 * a1[31] == 719890500;
  return 0LL;
}

这里就是相除,得到我们要的a1[]
脚本

a0 = 166163712 // 1629056
a1 = 731332800 // 6771600
a2 = 357245568 // 3682944
a3= 1074393000 // 10431000
a4= 489211344 // 3977328
a5 = 518971936 // 5138336
a6='_'
a7= 406741500 // 7532250
a8= 294236496 // 5551632
a9= 177305856 // 3409728
a10= 650683500 // 13013670
a11= 298351053 // 6088797
a12= 386348487 // 7884663
a13= 438258597 // 8944053
a14= 249527520 // 5198490
a15= 445362764 // 4544518
a16= 981182160 //10115280
a17= 174988800 // 3645600
a18= 493042704 // 9667504
a19= 257493600 // 5364450
a20= 767478780 // 13464540
a21= 312840624 // 5488432
a22= 1404511500 // 14479500
a23= 316139670 // 6451830
a24= 619005024 // 6252576
a25= 372641472 // 7763364
a26= 373693320 // 7327320
a27= 498266640 // 8741520
a28= 452465676 // 8871876
a29= 208422720 // 4086720
a30= 515592000 // 9374400
a31= 719890500 // 5759124

print(chr(a0),chr(a1),chr(a2),chr(a3),chr(a4),chr(a5),a6,chr(a7),chr(a8),chr(a9),chr(a10),chr(a11),chr(a12),chr(a13),chr(a14),chr(a15),chr(a16),chr(a17),chr(a18),chr(a19),chr(a20),chr(a21),chr(a22),chr(a23),chr(a24),chr(a25),chr(a26),chr(a27),chr(a28),chr(a29),chr(a30),chr(a31))

我们缺少一位a6,现在得到的flag是flag{e65421110ba03099a1c039337},a6并没有给我们,那就从0开始一个一个试,到1的时候成功了
最后的flag为flag{e165421110ba03099a1c039337}

25.[WUSTCTF2020]level1

打开这个附件可以看到有两个文件
在这里插入图片描述
打开txt文档,看到的是一堆数字,暂时看不明白有啥用
在这里插入图片描述
我们打开另一个文件,首先看到是64位文件
在这里插入图片描述
拖进IDA里面看一下,代码非常简单,就是我们输入的数经过下面的运算,写到了txt文件中,单数是位移,偶数是乘法
在这里插入图片描述
我们逆着写一个代码,逆推回去,要注意i是从1开始的,但是数组的下标是从0开始的
看一下脚本

data = [198,232,816,200,1536,300,6144,984,51200,570,92160,1200
		,565248,756,1474560,800,6291456,1782,65536000]
flag = ' '

for i in range(1,20):
        if i&1:
                flag+=chr(data[i-1]>>i)
        else:
                flag+=chr(data[i-1] // i)
print(flag)

得到flag
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值