Reverse


来自 BuuCTF

Java逆向解密

将题目用jd-gui打开,观察main函数
result 与 keyList相同,将keyList亦或回去就好了
tap1

KEY = [
    180, 136, 137, 147, 191, 137, 147, 191, 148, 136,
    133, 191, 134, 140, 129, 135, 191, 65]
result = ""
for i in range(0,len(KEY)):
    result += chr((KEY[i] ^ 0x20) - 0x20)# 加减优先级高于^
print(result)

[GXYCTF2019]luck_guy

首先ELF文件,运行其,发现提示我们不能发现flag在2333,我们就用2333,结果可想而知,不能发现flag,通过IDA分析,发现其必是经过451,输入451还是得不到flag,只能分析,脚本破解
tap1

f2处strcat处出现强制转换,小端序存储的读取问题,上个文章有解释,反序读取;h键将s转为16进制数,依照451顺序排解

flag = 'GXY{do_not_'
f2 = [0x7F, 0x66, 0x6F, 0x60, 0x67, 0x75, 0x63, 0x69][::-1]
s = ''
for i in range(8):
    if i % 2 == 1:
        s = chr(int(f2[i]) - 2)
    else:
        s = chr(int(f2[i]) - 1)
    flag += s
print(flag)

[BJDCTF2020]JustRE

下载并运行文件,发现有一个getflag选项,点击有试试这个,出现以下显示,click it,点了1k多下,还不要显示,果断放弃,换思路,这是捷径=不存在的弟弟,还是常规方法吧,想想flag一定会显示在这文本框上,拖入ollydbg
tap1

右键查找所有参考文本字串,发现如下图,简单出现flag,双击点到当地,在上方下断点
tap2

F8步过,走到jnz关键跳转处,发现跳转已实现,我们的目的是让其不实现,改变标志位即可
tap3

flag出现
answer

刮开有奖

下载并运行文件,说的是刮开有奖,很显然flag应该在里面,但是我们刮不开,很尴尬,
打开文件F5伪代码,得到flag的代码如下

 DialogBoxParamA(hInstance, (LPCSTR)0x67, 0, DialogFunc, 0); 	//	模式对话框,将DialogFunc函数传入模式

// 进入DialogFunc函数
if ( (_WORD)a3 == 1001 )
  {
    memset(String, 0, 0xFFFFu);
    GetDlgItemTextA(hDlg, 1000, String, 0xFFFF);		// 创建输入对话框
    if ( strlen(String) == 8 )							// 从内存分配上看出,以下变量连续,相当于一个数组
    {
      v7[0] = 90;
      v7[1] = 74;
      v8 = 83;
      v9 = 69;
      v10 = 67;
      v11 = 97;
      v12 = 78;
      v13 = 72;
      v14 = 51;
      v15 = 110;
      v16 = 103;
      sub_1310F0((int)v7, 0, 10);					// 对数组v7传入函数操作
      memset(v18, 0, 0xFFFFu);
      v18[0] = String[5];
      v18[2] = String[7];
      v18[1] = String[6];
      v4 = sub_131000((int)v18, strlen(v18));		// v4,v5分别对字符串后三位,后三位的前三位进行传入函数操作
      memset(v18, 0, 0xFFFFu);
      v18[1] = String[3];
      v18[0] = String[2];
      v18[2] = String[4];
      v5 = sub_131000((int)v18, strlen(v18));
      if ( String[0] == v7[0] + 34			//	得到flag
        && String[1] == v10
        && 4 * String[2] - 141 == 3 * v8
        && String[3] / 4 == 2 * (v13 / 9)
        && !strcmp(v4, "ak1w")
        && !strcmp(v5, "V1Ax") )
      {
        MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
      }
    }
    return 0;
  }

点进 sub_1310F0函数,发现其为一个算法,将其直接拉进vs,根据代码进行求解,if语句用来判断flag,逆向它得到flag前四位;由于v4,v5是经过sub_131000(base64)加密的,对其直接解密即可
ak1w = jMp ,V1Ax = WP1,连接字符串,得到flag{UJWP1jMp}

 // sub_1310F0 为以下函数,其中DOWRD*前有一个下划线 “_” ,在将伪代码变为c代码时,去掉下划线
#include <stdio.h>
#include <iostream>
#include<windows.h>
using namespace std;

int __cdecl sub_1310F0(int 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 = 4 * i;
        v6 = *(DWORD*)(4 * i + a1);
        if (a2 < result && i < result)
        {
            do
            {
                if (v6 > *(DWORD*)(a1 + 4 * result))
                {
                    if (i >= result)
                        break;
                    ++i;
                    *(DWORD*)(v5 + a1) = *(DWORD*)(a1 + 4 * result);
                    if (i >= result)
                        break;
                    while (*(DWORD*)(a1 + 4 * i) <= v6)
                    {
                        if (++i >= result)
                            goto LABEL_13;
                    }
                    if (i >= result)
                        break;
                    v5 = 4 * i;
                    *(DWORD*)(a1 + 4 * result) = *(DWORD*)(4 * i + a1);
                }
                --result;
            } while (i < result);
        }
    LABEL_13:
        *(DWORD*)(a1 + 4 * result) = v6;
        sub_1310F0(a1, a2, i - 1);
        result = a3;
        ++i;
    }
    return result;
}

int main(void)
{
    int v7[] = { 90 ,74 ,83,69,67,97,78,72,51,110,103 };
    sub_1310F0((int)&v7, 0, 10);
    
    cout << (char)(v7[0] + 34);
    cout << (char)v7[4];
    cout << (char)((v7[2] * 3 + 141) / 4);
    cout << (char)(v7[7] / 9 * 2 * 4);						// UJWP

    return 0;
}

主要讲解

简单的注册器

IDE打开,什么都看不懂,更换apk反编译软件,用jeb打开,tab键生成伪代码,发现flag出现在里面如下显示
前面部分没有截取。v9 = 2,v2 = 1,v11 = 0x1F
tap1
直接上脚本,得到flagflag{59acc538825054c7de4b26440c0999dd}

flagtxt = "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): 		# 从伪代码发现就是让 v5[0x1F - v4] 与 v5[v4] 内容交换
    x[i],x[31-i] = x[31-i],x[i]
print ("flag{"+ ''.join(x) + "}")

pyre

pyc文件,当然我不知道是什么,百度呗
百度后得知用python反编译工具打开,分享一个python反编译在线网站 https://tool.lu/pyc/

print 'Welcome to Re World!'
print 'Your input1 is your flag~'
l = len(input1)              
for i in range(l):           
    num = ((input1[i] + i) % 128 + 128) % 128  # +128,再 %128,对于这个代码来说都是无用功,flag肯定不会超过128
    code += num

for i in range(l - 1):
    code[i] = code[i] ^ code[i + 1]   

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

根据伪代码,反推出flag

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

for i in range(len(code)-2,-1,-1): 			# 倒数第二个字母开始,到第0个
    code[i]=chr(ord(code[i])^ord(code[i+1]))

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

easyre

拖进PE,发现为upx壳32bit程序,upx -d +文件路径 脱壳
tap1
拖进IDA,分析局部变量,时连续开辟的内存,并且发现如下内容
tap2
出现flag的的形式,v10为"}",则前面连续的空间为flag的内容,接着就是求那些连续空间的内容即可

tap3
跑脚本

#  r:防特殊字符转义
str = r'~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('+chr(0x27)+r'&%$# !"'
v4 = [42,70,39,34,78,44,34,40,73,63,43,64]

flag = ''

for i in v4:
    flag += chr(str.find(chr(i)) + 1)

print(flag) # U9X_1S_W6@T?

findit

下载文件下来,apk文件,拖进apkIDE中仅仅发现一串不知名的16进制数字,转换为字符为pvkq{m164675262033l4m49lnp7p9mnk28k75},是不是有点flag的样子,这也是猜的;
接下来拖进jeb中,看看有什么发现,发现了以下代码,更加证实了上面的猜想

new View$OnClickListener(new char[]{'T', 'h', 'i', 's', 'I', 's', 'T', 'h', 'e', 'F', 'l', 'a', 'g', 'H', 'o', 'm', 'e'}, this.findViewById(0x7F05003E), new char[]{'p', 'v', 'k', 'q', '{', 'm', '1', '6', '4', '6', '7', '5', '2', '6', '2', '0', '3', '3', 'l', '4', 'm', '4', '9', 'l', 'n', 'p', '7', 'p', '9', 'm', 'n', 'k', '2', '8', 'k', '7', '5', '}'}

并且发现以下代码,且前面的一串刚好为38位。下面代码必是对这38位字符进行加密操作,认真分析一下;
v8 = 65,v9 = 90,v10 = 122,v7 = 97

一步步分析,上述的38位串全部都能进入if(this.val$b[v0] < v8 || this.val$b[v0] > v9)语句;

  • 当字符为小写时,进入if(this.val$b[v0] >= v7 && this.val$b[v0] <= v10),下一个if语句的v4[0] <= v9内容就不必看,一定不成立,就是看后面,字符串中字母对应ASCII最小为ll = 108 + 16 = 124,124对应|,也就是说这个if语句没用,不可能进去接着就-26,也就是字母ASCII减去10;

  • 当字符为数字时,直接就是this.val,不发生变化

了解过凯撒的就好写了,这就是一个简单的凯撒加密,不过它利用的是goto语句来实现的;
直接搜索在线凯撒加密或者python脚本来自https://blog.csdn.net/qq_63792137/article/details/123169867,key = 10flag{c164675262033b4c49bdf7f9cda28a75}
tap1
GCC指令

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值