攻防世界 Reverse 新手区 wp

5 篇文章 1 订阅
0 篇文章 0 订阅

学习逆向也有一段时间了 也是对于这段时间的一个总结

准备

正所谓工欲善其事必先利其器,逆向之前要准备好我们的家伙什儿

IDA

链接:https://pan.baidu.com/s/1tCijS4s_g6KFwV9ycCPVkw
提取码:nd46
反编译工具,还有各种插件实现不同功能,主要应用于静态分析

Ollydbg

吾爱破解专用版就不戳,可能会报毒,一般破解软件会报毒
动态分析神器
爱盘

dnSpy

.NET逆向

jd-dui

.jar文件逆向

exeinfope

软件查壳

linux环境

逆向分析中较多elf文件需要在linux环境下调试分析,可以gdb动态调试elf,也可以配合IDA进行动态调试

IDA动调可参考

.py文件逆向

.py逆向可以通过线上反编译
.py文件在线反编译

正文

01 open-source

题目叫开源,就真开源呗,附件.c文件

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

int main(int argc, char *argv[]) {
    if (argc != 4) {
    	printf("what?\n");
    	exit(1);
    }

    unsigned int first = atoi(argv[1]);
    if (first != 0xcafe) {
    //first == 0xcafe 跳过
    	printf("you are wrong, sorry.\n");
    	exit(2);
    }

    unsigned int second = atoi(argv[2]);
    if (second % 5 == 3 || second % 17 != 8) {
    //second % 17 == 8 && second % 5 != 3 
    	printf("ha, you won't get it!\n");
    	exit(3);
    }

    if (strcmp("h4cky0u", argv[3])) {
    //argv[3] == h4cky0u len == 7
    	printf("so close, dude!\n");
    	exit(4);
    }

    printf("Brr wrrr grr\n");

    unsigned int hash = first * 31337 + (second % 17) * 11 + strlen(argv[3]) - 1615810207;

    printf("Get your key: ");
    printf("%x\n", hash);
    return 0;
}


代码审计
经过三个判断输出flag(hash值)

int first = 0xcafe;
unsigned int hash = first * 31337 + 8 * 11 + 7 - 1615810207;
printf("%x\n", hash);

c0ffee

02 simple-unpack

查壳,upx壳,还是elf文件,kali命令脱壳
在这里插入图片描述
IDA载入
在这里插入图片描述
开幕雷击
flag{Upx_1s_n0t_a_d3liv3r_c0mp4ny}

03 logmein

IDA
找到main f5反汇编
在这里插入图片描述
4007C0函数输出密码错误
脚本输出flag
eg.大数v7代码中8个字节拆分为8份调用

string a = ":\"AL_RT^L*.?+6/46";
long long v7 = 28537194573619560LL;
for (int i = 0; i < a.size(); i++)
{
	cout << (char)(*((char*)&v7 + i % 7) ^ a[i]);
}	

RC3-2016-XORISGUD

04 insanity

IDA
在这里插入图片描述
生成随机数
先查看strs值
9447{This_is_a_flag}
在这里插入图片描述
这就是flag。。。。
在这里插入图片描述
hhhh

05 getit

直接IDA开干

f5 反汇编

在这里插入图片描述
直接看到文件操作 生成文件名为flag.txt 大胆猜测应该是经过操作在文件中生成flag

分析各种字符串
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
可知

s = { "c61b68366edeb7bdce3c6820314b7498" };
t = { "SharifCTF{????????????????????????????????}" }
u = { "*******************************************" }

分析一开始的循环

在这里插入图片描述
脚本得到处理之后的字符串t

char s[100] = { "c61b68366edeb7bdce3c6820314b7498" };
char t[100] = { "SharifCTF{????????????????????????????????}" }
for (int i = 0; i < s.length(); i++)
{
	if (i & 1)                     
   		v3 = 1;
	else
		v3 = -1;
	t[i+10] = (char)(s[(signed int)i] + v3);
}

得到新的字符串t

char t[100] = { "SharifCTF{b70c59275fcfa8aebf2d5911223c6589}" };

对于int 数组 p[43] 观察到汇编代码中以十六进制四字节存储 组成p[43]

在这里插入图片描述

int p[43] = {30,24,25,32,40,36,28,17,34,39,16,33,19,26,5,3,29,27,31,4,8,15,37,42,14,41,2,23,21,0,10,20,7,11,1,13,6,38,18,35,12,22,9 };

文件操作直接脚本

#include <bits/stdc++.h>
using namespace std;
int main()
{
	int v3;
	char s[100] = { "c61b68366edeb7bdce3c6820314b7498" };
	char b[100] = { "b70c59275fcfa8aebf2d5911223c6589" };
	char u[100] = { "*******************************************" };
	char t[100] = { "SharifCTF{b70c59275fcfa8aebf2d5911223c6589}" };
	int p[43] = {30,24,25,32,40,36,28,17,34,39,16,33,19,26,5,3,29,27,31,4,8,15,37,42,14,41,2,23,21,0,10,20,7,11,1,13,6,38,18,35,12,22,9 };
	
	FILE * stream;
	char * filename;
	filename = new char;
	strcpy(filename, "flag.txt");//直接源目录生成文件
	stream = fopen(filename, "w");//打开文件
	fprintf(stream, "%s\n", u, strlen(s));//以字符串u初始化文件
	for (int i = 0; i < strlen(t); ++i)
	{
		fseek(stream, p[i], 0);//转移文件指针至一定位置
		fputc((char)*(t + p[i]),stream);//修改转移后文件位置的字符
		//以下代码将flag再次初始化为u 迷惑操作 注释掉
		//fseek(stream, 0LL, 0);
		//fprintf(stream, "%s\n", u);
	}
	fclose(stream);
	//remove删掉flag文件 注释掉
	//remove(filename);
	return 0;
}

在这里插入图片描述
奥里给

SharifCTF{b70c59275fcfa8aebf2d5911223c6589}

06 python-trade

.py在线反编译
https://tool.lu/pyc/在这里插入图片描述
简单算法逆向

python脚本

import base64
correct = "XlNkVmtUI1MgXWBZXCFeKY+AaXNt"
flag = ''
correct = base64.b64decode(correct)
for i in correct:
    s = i
    s -= 16
    flag += chr(s ^ 32)
print(flag)

nctf{d3c0mpil1n9_PyC}

07 re1

载入IDA分析

f5反汇编main函数

在这里插入图片描述

  v3 = strcmp((const char *)&v5, &v9);

重要判断条件 比较v5字符串和v9字符串

双击进入unk_413E90函数显示字符串get flag

在这里插入图片描述
v5应与v9相同

_mm_storeu_si128((__m128i *)&v5, _mm_loadu_si128((const __m128i *)&byte_413E34));

作用类似于strcpy,将413E34值赋给v5
在这里插入图片描述
但是由于字符串结束判断条件为\0字符 即值为0的字节

而第一个0出现在413E44结尾,故整个判断字符串v5为DUTCTF{We1c0met0DUTCTF}

即为flag

eg. 关于data数据中可以通过快捷键 ‘r’ 将16进制数转换为字符

08 game

打开程序发现是一个关于开灯的游戏
在这里插入图片描述输入不同的数字N可以改变第N排的灯,但是其周围的灯也会受到影响,可以通过分析得到答案(hhh)

既然不是输入key 那么就可以动调出答案
ida先瞅一眼
在这里插入图片描述直接看main函数下面的关键判断,推断457AB4为结果

双击进入查看在这里插入图片描述
发现关键字符串,也可通过Ctrl+T搜索字符串发现

并且可以发现,下面就是flag生成过程
这样静态分析也可以咯

静态

在这里插入图片描述

两个异或 上面的一大堆数据相当于两个数组 变量在内存中顺序排列,所以*(&v2+i)就可以遍历v2下面的一系列变量的值 v59同理

脚本

a=[18,64,98,5,2,4,6,3,6,48,49,65,32,12,48,65,31,78,62,32,49,32,1,57,96,3,21,9,4,62,3,5,4,1,2,3,44,65,78,32,16,97,54,16,44,52,32,64,89,45,32,65,15,34,18,16,0]
# v59-v115
b=[123,32,18,98,119,108,65,41,124,80,125,38,124,111,74,49,83,108,94,108,84,6,96,83,44,121,104,110,32,95,117,101,99,123,127,119,96,48,107,71,92,29,81,107,90,85,64,12,43,76,86,13,114,1,117,126,0]
# v2-v58
flag = ''
for i in range(56):
    b[i] ^= a[i]
    flag += chr(b[i]^0x13)
print(flag)

zsctf{T9is_tOpic_1s_v5ry_int7resting_b6t_others_are_n0t}

动态

祭出神器OD

在这里插入图片描述
回顾一下最后判断条件的部分
可以看到在判断条件之前出现字符串CLS 可以通过这个字符串入手找到判断跳转

主线程右键中文搜索引擎智能搜索 进入字符串界面 右键Find查找CLS
在这里插入图片描述双击跟进
在这里插入图片描述
IDA和OD的虚拟地址后几位都是一样的
所以将参数"CLS"推进栈后调用的00F581B7函数就是j_system函数

在这里插入图片描述

下面一连串jnz判断跳转 最后call 输出flag的函数00F57AB4

直接跳过jnz jmp到00F57AB4
在这里插入图片描述

在这里插入图片描述

运行
在这里插入图片描述

zsctf{T9is_tOpic_1s_v5ry_int7resting_b6t_others_are_n0t}

09 Hello, CTF

载入IDA main函数F5反编译
在这里插入图片描述
简单的算法 将输入的字符串转化为16进制码与v13比较

在线转码

CrackMeJustForFun

10 no-strings-attached

elf文件 可能面临linux运行调试

IDA瞅瞅
在这里插入图片描述main函数里面 这个authenticate是主要函数
在这里插入图片描述函数还是比较简单的 虽然有一些wchar_t这样的陌生的数据形式 但是基本能猜到
s2为加密后的字符串 输入字符串和其比较
看看参数 s 和 8A90里面是什么
在这里插入图片描述

在这里插入图片描述
大概猜到这种类型数据占用4个Byte 真正存储数据的只有第一个Byte 因为其余三个Byte数据要么重复 要么没有价值
先用IDC内置脚本把s串内容搞出来

auto i;
for(i=0;;i++)
{
    Message("0x%x,",Byte(0x8048AA8+4*i));
    if(!Byte(0x8048AA8+4*i))
        break;
}
//shift+F2 打开IDA脚本编辑界面 IDA提供IDA(类C)和python两种语言

在这里插入图片描述

s = [0x3a,0x36,0x37,0x3b,0x80,0x7a,0x71,0x78,0x63,0x66,0x73,0x67,0x62,0x65,0x73,0x60,0x6b,0x71,0x78,0x6a,0x73,0x70,0x64,0x78,0x6e,0x70,0x70,0x64,0x70,0x64,0x6e,0x7b,0x76,0x78,0x6a,0x73,0x7b,0x80,0x0,]

再看看decrypt

在这里插入图片描述
可以看到算法很简单,但是a2参数只有5个字符,而i越界,两个参数在内存中连续储存,所以a2越界后取到s字符串的值,相当于a2 = a2 + s

脚本

#include <bits/stdc++.h>
using namespace std;
int main()
{
	vector<int> s = { 0x3a,0x36,0x37,0x3b,0x80,0x7a,0x71,0x78,0x63,0x66,0x73,0x67,0x62,0x65,0x73,0x60,0x6b,0x71,0x78,0x6a,0x73,0x70,0x64,0x78,0x6e,0x70,0x70,0x64,0x70,0x64,0x6e,0x7b,0x76,0x78,0x6a,0x73,0x7b,0x80,0x0 };
	vector<int> a2 = { 0x1,0x2,0x3,0x4,0x5,0x0,0x3a,0x36,0x37,0x3b,0x80,0x7a,0x71,0x78,0x63,0x66,0x73,0x67,0x62,0x65,0x73,0x60,0x6b,0x71,0x78,0x6a,0x73,0x70,0x64,0x78,0x6e,0x70,0x70,0x64,0x70,0x64,0x6e,0x7b,0x76,0x78,0x6a,0x73,0x7b,0x80,0x0 };
	int v4, v6, v7, i;
	v4 = 0;
	v6 = s.size();
	v7 = 5;
	while (v4 < v6)
	{
		for (i = 0; i < v7 && v4 < v6; ++i)
			s[v4++] -= a2[i];
	}
	for (i = 0; i < s.size(); i++)
		cout << (char)s[i];
}

9447{you_are_an_international_mystery}

11 csaw2013reversing2

程序先进IDA看看
在这里插入图片描述
可见开了一段堆空间 sub_40102A函数永返回0
如果是动态debug时会进入循环结束进程
lpMem中存储乱码数据
经过sub_401000函数生成flag
但是没有生成对话框显示flag
不是debug时出现对话框显示flag
程序跑一下看看
在这里插入图片描述
输出乱码
动态调试 尝试运行401000函数后跳入对话框显示flag

开始是一个函数 F7步入

在这里插入图片描述

在这个函数出现对话框 下断点重新载入F7步入

在这里插入图片描述

步入继续运行看到停在MessageBox函数处
在这里插入图片描述

单步运行 找到判断条件IsDebuggerPresent()和102A函数

在这里插入图片描述

继续单步运行发现下面的跳转已实现 直接跳到MessageBox参数进栈时

在这里插入图片描述
所以要让跳转不实现 nop掉该je跳转 而下面的int3中断了程序 也nop掉

在这里插入图片描述继续运行进程会直接结束 所以在函数结束时跳转至原MessageBox处

在这里插入图片描述
在这里插入图片描述flag{reversing_is_not_that_hard!}

12 maze

maze是迷宫的意思 所以这道题多少跟走迷宫沾点边

IDA看一看

在这里插入图片描述
进入main函数 首先看到输入后的第一个判断条件
长度必须是24而且以nctf{}为格式

下面是一波操作 先往后稍稍 送结果看起

在这里插入图片描述

看到一个数组的值不等于35(’#’)的话就跳转到Wrong Flag
从结构来看

  • 8 * v10 + SHIWORD(v10)

有点像二维数组用一维数组储存的取值方法
对应题目迷宫 可能出现一个8*8的地图

看下asc_601060的值
在这里插入图片描述
一个64位数组 随便写个脚本弄出地图
在这里插入图片描述

可以看到要从左上走到#

右下右右下下左下下下右右右右上上左左

a = "  *******   *  **** * ****  * ***  *#  *** *** ***     *********"
index = 0
for i in range(8):
    f = ''
    for i in range(8):
        f += a[index]
        index += 1
    print(f)
  ******
*   *  *
*** * **
**  * **
*  *#  *
** *** *
**     *
********

再向上分析这个迷宫是怎么走的

在这里插入图片描述上面有四个分支

有Oo.0四种字符

可以猜测对应上下左右了

再看看对应函数确认一下

在这里插入图片描述

在这里插入图片描述Oo.0分别对应 左右上下

nctf{o0oo00O000oooo…OO}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值