当前位置:   article > 正文

[CTF]buuctf reverse解题笔记_apkide ctf

apkide ctf

做题步骤总结

(1)做题步骤:
双击exe文件看有无信息
使用查壳软件查壳,了解程序是多少位的(64位或32位)
使用ida进行分析
(2)ida分析过程:
Shift+F12查看一下字符串,寻找关键词(如flag等) ,如没有关键词,就在main函数里查找信息
双击字符串,查看包含该字符串的位置,查看引用该字符串的详细地址
ctrl+x(交叉引用)查看是哪段函数调用了该字符串
使用F5反汇编,查看伪C代码
分析伪代码(选中数字后按键盘“R”键,即可将数字转换为字符;选中变量后 ,按下键盘“X”键查看该变量的交叉引用)
(3)工具下载网站
逆向工具下载

easyre

用notepad++打开附件,直接ctrl+F搜索就能找到
flag{this_Is_a_EaSyRe}
在这里插入图片描述

reverse1

参考文章:BUUCTF-reverse-reverse1(面向新手超详细)
先用DIE查下壳,是PE文件(exe文件是属于PE文件的一种)
显示64位,无壳
加壳的目的:为了隐藏程序真正的OEP(入口点),防止被破解
在这里插入图片描述
用IDA64位打开,先用shift + F12(不行的话再+Fn试试)查找一下flag关键词
在这里插入图片描述
双击进入该字符串位置
在这里插入图片描述
ctrl+x(交叉引用)查看是哪段函数调用了该字符串
在这里插入图片描述
点击“OK”进入该段程序
在这里插入图片描述
按“F5”查看伪C代码
在这里插入图片描述
然后对代码进行分析
strncmp()是字符串比较函数,代码表示如果str1和str2的前v5位相等,则输出"this is the right flag"
可以猜测 "sub_1400111D1"是"printf"之类的输出函数
在这里插入图片描述
接着往上分析的其他语句,看看str1和str2的具体内容是什么
可以猜测 “sub_14001128F"是"scanf"之类的输入函数,字符串str1为我们输入的内容
在这里插入图片描述
然后分析一下str2
随便双击一个str2,点进去后找到是一个字符串 ‘{hello_world}’
在这里插入图片描述
继续往上分析代码
发现对str2做了替换处理,将ascii码为111的字符转换ascii码为48的字符
在这里插入图片描述
选中数字按"R"键可以将数字转换为字符
在这里插入图片描述
str2中所有的"o"都被转换成了"0”
所以flag为 flag{hell0_w0rld}

reverse2

先用DIE查下壳,显示64位,不是exe文件,而是一个ELF文件,ELF文件是linux平台上常见的可执行文件
在这里插入图片描述
用IDA64位打开,通过流程图可以找到关键字:flag
认为offset flag就是flag地址,直接双击进入
在这里插入图片描述
这段字符有点像flag的格式,尝试提交发现不对
在这里插入图片描述
找到左侧的main函数,按“F5”查看伪C代码
在这里插入图片描述
s2是我们输入的字符串,将flag字符串和s2对比,如果一致,则是正确的flag
在这里插入图片描述
往上分析代码,发现flag字符串被做了替换处理,将ascii码为105和114的字符转换ascii码为49的字符
在这里插入图片描述
选中数字按"R"键可以将数字转换为字符,flag中所有的’i’和’r’都被转换成了’1’
在这里插入图片描述
也可以编写python脚本得到flag

key = '{hacking_for_fun}'
flag = 'flag'
for i in key:
    if i=='i' or i=='r':
        flag = flag + '1'
    else:
        flag = flag + i
print(flag)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

flag{hack1ng_fo1_fun}

内涵的软件

下载的附件先运行一下,输入y或者n,程序都会自动退出
在这里插入图片描述
先用DIE查下壳,显示32位
在这里插入图片描述
用32位的IDA打开
在这里插入图片描述
按“F5”查看伪C代码,发现里面还有一个main_0()的函数,直接双击进入
在这里插入图片描述
发现一段变量名为v5的可疑字符串,但是代码并未调用v5
在这里插入图片描述
结合最开始程序运行的提示:“这里本来应该是答案的,但是粗心的程序员忘记把变量写进来了,你要不逆向试试看:(Y/N)”
可以猜测程序员忘记调用v5,尝试提交这段字符串(记得花括号前加上flag):
flag{49d3c93df25caad81232130f3d2ebfad}
提交后显示正确

新年快乐

先看看题目要求,flag是一个字符串
在这里插入图片描述
用DIE查下壳,显示32位,发现有UPX的壳
在这里插入图片描述
下载脱壳工具:upx脱壳工具
在文件目录输入cmd
在这里插入图片描述
在终端打开该工具,输入:upx -d 存放exe文件的目录
显示脱壳成功
在这里插入图片描述
用32位的IDA打开脱壳后的exe文件,shift+F12查看所有字符串,找到带flag的语句双击进入
在这里插入图片描述
ctrl+x(交叉引用)查看是哪段函数调用了该字符串,点OK
在这里插入图片描述
按“F5”查看伪C代码
其中Str2是"HappyNewYear!"字符串,Str1是我们输入的内容
strncmp()函数比较Str1和Str2字符串,相等则说明是正确的flag
在这里插入图片描述
提交flag{HappyNewYear!},显示正确

xor

用IDA64位打开附件,按“F5”查看伪C代码
在这里插入图片描述
要求输入的字符串_b长度为33
在这里插入图片描述
从第2个字符开始,每一个都与前一个做异或运算
在这里插入图片描述
运算得到的字符串与global比较,如果相同,字符串就是flag
在这里插入图片描述
找到global的值
在这里插入图片描述
选中上面这些字符,shift+E导出数据,选中十六进制格式
在这里插入图片描述
编写python脚本

# 定义一个列表key
key = [
    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, 0x00
]
flag = ''
# 遍历key中的元素,从最后一个元素(索引为 len(key)-1)开始到第一个元素(索引为 0),向前依次进行操作。
for i in range(len(key)-1,0,-1):
    # 对每个元素进行异或运算,将当前元素与前一个元素(key[i-1])进行异或,然后将结果保存到当前元素位置(key[i])上。
    key[i] ^= key[i-1]
for i in range(len(key)):
    # 将每个元素转换为对应的ASCII字符,按顺序拼接起来
    flag += chr(key[i])
print(flag)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

打印出结果,得到flag:
flag{QianQiuWanDai_YiTongJiangHu}

helloword

下载附件得到一个apk文件(apk是AndroidPackage的缩写,即Android安装包)
在这里插入图片描述
将后缀改为zip即可打开看到该文件内容
在这里插入图片描述
方法一(用ida)
可以直接打开zip格式的文件
也可以把apk文件拖入ida中,选中apk格式打开
在这里插入图片描述
按shift+F12查找字符串即可找到flag
在这里插入图片描述
方法二(用APKIDE)
安卓逆向工具下载地址:https://down.52pojie.cn/Tools/Android_Tools/
打开apk文件,在右侧搜索flag{即可找到
在这里插入图片描述
flag{7631a988259a00816deda84afb29430a}

reverse3

先用DIE查下壳,显示32位,无壳
在这里插入图片描述
用ida32位打开,按F5查看伪C代码
在这里插入图片描述
双击进入main_0函数
在这里插入图片描述
接下来分析代码内容
str是我们输入的字符串
在这里插入图片描述
使用一个sub_4110BE()函数得到v4的值,然后复制给Dest
在这里插入图片描述
对Dest字符串做一个简单的循环运算
第一次循环:Dest[0]+0 第二次为:Dest[1] +1 …
在这里插入图片描述
如果Dest和str2相等时,flag正确,所以Str2为flag经过变换后的字符串
在这里插入图片描述
点进去看一下str2的值为:e3nifIH9b_C@n@dH
在这里插入图片描述
变化前的Dest从v4来,得到v4的sub_4110BE有什么作用我们不清楚,点进去看看
这个函数看上去很复杂,自己很难分析出来实现了什么具体功能
在这里插入图片描述
代码的后面有一个叫aAbcdefghijklmn的数组,点进去看看,发现是base64编码表
在这里插入图片描述
所以还原的思路为:将Str2还原为Dest,再对Dest进行base64解码

import base64

Des = "e3nifIH9b_C@n@dH"
flag = ""

for i in range(len(Des)):
    # ord()函数返回字符对应的ASCII数值
    # chr()函数将结果转换为对应的字符
    flag += chr(ord(Des[i]) - i)
print(base64.b64decode(flag))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

得到flag{i_l0ve_you}

不一样的flag

下载附件运行一下,要求输入数字操作
在这里插入图片描述
用DIE查下壳,显示32位,无壳
在这里插入图片描述
用32位ida打开,按F5查看伪c代码,分析一下这段代码
在这里插入图片描述
在这里插入图片描述
将25个字节的字符串复制到v3
在这里插入图片描述
v5是我们输入的操作数
在这里插入图片描述
49和35的ascii码正好对应1和#,上面那个v3字符串也有1和#
当等于1时,退出程序;等于#时,表示输入的顺序是正确的flag
在这里插入图片描述
结合上面那一大堆0、1字符串和“up”"down"等提示,猜想这道题是一个迷宫
通过第51行代码的5 * ,说明这是一个5行5列的迷宫(一共25个字符)
在这里插入图片描述
遇到1会退出,所以要避开1,得到flag{222441144222}

simpleRev

参考文章:[BUUCTF] simpleRev (涉及大小端序存储)
用DIE查下壳,显示64位,无壳
在这里插入图片描述
用ida64位打开,按F5查看伪C代码,有一个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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70

分析一下代码内容
首先定义了一些变量,src和v9的内容比较特殊,按R转换一下
src=‘SLCDN’ v9=‘wodah’
数据存储是按照大端模式进行,但在读取时需要注意大小端序,下面是以char格式读取,故读取用小端序
在这里插入图片描述
text由key3和v9连接而成
在这里插入图片描述
可以看到key3=‘kills’,v9=‘wodah’
所以text=‘killshadow’ (v9为小端序,故读取时要逆序)
在这里插入图片描述
将key1的值复制给 key,将 src 接在 key 后面
其中 key1 = ‘ADSFK’ , *src = ‘SLCDN’
所以key = ‘ADSFKNDCLS’ (src 为小端序,故读取时要逆序)
在这里插入图片描述
64和90对应的ascii值为’@‘和’Z’
这个循环的作用就是将key数组中ASCII码在64和90之间的字符都加32,实际上就是把key数组中的大写字母全部变成小写字母,key字符串变为’adsfkndcls’
在这里插入图片描述
v1是我们输入的flag值,这个循环对v1做了一系列的变换,并将变换后的值放在了str2中
在这里插入图片描述
比较text和变换后的值str2,如果相等,则我们的输入是正确的flag
在这里插入图片描述
所以就要思考怎么推出str2变换前的v1值(也就是我们输入的值)
可以用暴力破解的方法,将每一个字母都带入处理的式子中,并将结果与text中的进行对比,找到使结果成立的字母

flag = ''
text = 'killshadow'
key = 'adsfkndcls'
for i in range(len(text)):
    for x in range(65,123):
        if text[i] == chr((x - 39 - ord(key[i]) + 97) % 26 + 97):
            flag += chr(x)
            break
print('flag{'+flag+'}')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

flag{KLDQCUDFZO}

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/546422
推荐阅读
相关标签
  

闽ICP备14008679号