来自 BuuCTF
Java逆向解密
将题目用jd-gui打开,观察main函数
result 与 keyList相同,将keyList亦或回去就好了
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,只能分析,脚本破解
在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
右键查找所有参考文本字串,发现如下图,简单出现flag,双击点到当地,在上方下断点
F8步过,走到jnz
关键跳转处,发现跳转已实现,我们的目的是让其不实现,改变标志位即可
flag
出现
刮开有奖
下载并运行文件,说的是刮开有奖,很显然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
直接上脚本,得到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 +文件路径 脱壳
拖进IDA,分析局部变量,时连续开辟的内存,并且发现如下内容
出现flag的的形式,v10为"}",则前面连续的空间为flag的内容,接着就是求那些连续空间的内容即可
跑脚本
# 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最小为l
,l = 108 + 16 = 124
,124对应|
,也就是说这个if语句没用,不可能进去接着就-26,也就是字母ASCII减去10; -
当字符为数字时,直接就是this.val,不发生变化
了解过凯撒的就好写了,这就是一个简单的凯撒加密,不过它利用的是goto语句来实现的;
直接搜索在线凯撒加密或者python脚本来自https://blog.csdn.net/qq_63792137/article/details/123169867,key = 10
。flag{c164675262033b4c49bdf7f9cda28a75}
GCC指令