吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 16987|回复: 123
收起左侧

[CTF] 第二届广东省大学生网络攻防大赛 simple_re

  [复制链接]
muyilin 发表于 2022-5-31 22:31
本帖最后由 muyilin 于 2022-6-7 08:58 编辑

第二届广东省大学生网络攻防大赛 simple_re

流程总结:(思路及原文出自  JANlittle  师傅)
程序将关键函数以对象元素的形式存在对象里,然后在申请内存中搭配指针间接调用,关键是把内存空间中对应位置的函数和变量用流程图梳理清除。
sub_140002110 有反调试,主要是 IsDebuggerPresent 和获取 ThreadContext 并检测是否有硬件断点。
加密流程为先打乱每个字节的比特顺序,其实就是把比特串倒过来;然后利用打乱比特顺序的前 4 字节输入 SMC 解密一段代码,并开一个线程检测 SMC 解密后的代码段是否有 0xcc,有的话说明前 4 字节输入错误;之后调用上述代码段进行魔改 XTEA 加密。
.
.
下载程序,照例扔入 exeinfope 中查看信息:
在这里插入图片描述
.
.
64 位 exe 文件,无壳,照例扔入 IDA64 中查看伪代码,有 main 函数看 main 函数:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
.
.
第一部分是输入字符比特流倒序,接下来我们看第二部分:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
.
.
第二部分的 SMC 解密处后面再说,因为要用到第三部分的数据,所以卡住不要紧张,说不定答案在后面呢。现在我们来看第三部分:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
.
.
第三部分——用 Str1 的前 4 个字节生成 SMC 代码:

b=[  0x27, 0x44, 0x7F, 0xEB, 0x3A, 0x8F, 0x1A, 0x2E, 0xFB, 0x41, 
  0xE6, 0x46, 0xFB, 0x59, 0xEE, 0x42, 0xFB, 0x49, 0xD6, 0x46, 
  0xF9, 0x49, 0xEE, 0x85, 0x72, 0x85, 0xB3, 0xF6, 0x3A, 0x87, 
  0xB3, 0x16, 0xF9, 0x4C, 0xF2, 0x87, 0x37, 0xF8, 0x31, 0x4B, 
  0x82, 0x0C, 0xF6, 0x0E, 0x72, 0xCB, 0xB3, 0xE2, 0x0D, 0xA0, 
  0x9C, 0x89, 0xB5, 0x49, 0x0A, 0x0E, 0x72, 0x0C, 0xF6, 0x85, 
  0x37, 0xF0, 0xCD, 0x4B, 0x62, 0x03, 0x75, 0x8A, 0x72, 0x0C, 
  0xF6, 0x85, 0x37, 0xF8, 0x7B, 0x1A, 0xB7, 0x0C, 0xF6, 0x0E, 
  0x72, 0x87, 0xB3, 0xFA, 0xB3, 0xE4, 0xF0, 0x3F, 0xB0, 0x87, 
  0xB3, 0xFA, 0x73, 0xCE, 0x7D, 0x4B, 0x82, 0x8F, 0x16, 0x0D, 
  0x3A, 0x81, 0xFA, 0x8B, 0x72, 0x0C, 0xF6, 0x0E, 0x3A, 0x87, 
  0xB3, 0x2E, 0x3A, 0x0D, 0x3E, 0x85, 0x7A, 0x87, 0xB3, 0xFE, 
  0x73, 0xC4, 0xC7, 0xDE, 0x73, 0x49, 0x0E, 0x85, 0x37, 0xE0, 
  0xF7, 0x4B, 0x82, 0x87, 0xB3, 0xF6, 0xFF, 0x18, 0x33, 0x0E, 
  0x72, 0x0C, 0xF6, 0x85, 0x37, 0xF4, 0x37, 0xE6, 0x74, 0x3D, 
  0x34, 0x85, 0x37, 0xF4, 0xF7, 0xCC, 0xF9, 0x49, 0x06, 0xCF, 
  0x9A, 0x07, 0x7F, 0xCE, 0xF1, 0xEC, 0xF5, 0x46, 0xFF, 0x00, 
  0x73, 0x0E, 0x72, 0x0C, 0xF6, 0x46, 0xF9, 0x49, 0xD6, 0x46, 
  0x73, 0xC4, 0x7D, 0x06, 0xF9, 0x49, 0x06, 0x0F, 0xBA, 0x3D, 
  0x26, 0x0F, 0x37, 0xF8, 0x75, 0x4B, 0x8E, 0x0D, 0x1F, 0x7E, 
  0x8D, 0xF3, 0x09, 0x46, 0xF9, 0x49, 0xEE, 0x85, 0x27, 0xF4, 
  0x7F, 0x1E, 0x3A, 0x87, 0xB3, 0x16, 0x3A, 0x8F, 0x36, 0x0A, 
  0xF9, 0x59, 0x02, 0x87, 0x62, 0x9C, 0xBE, 0x8D, 0xB6, 0x2C, 
  0xAB, 0xCD]

Str1=[0x72, 0x0C, 0xF6, 0x0E]

address=0x140042000
for i in range(232):
    patch_byte(address+i,Str1[i%4]^b[i])

print("success")

在这里插入图片描述
在这里插入图片描述
.
.
最后梳理流程,写解密代码:(代码出自  JANlittle  师傅)
请添加图片描述
请添加图片描述

#include <stdio.h>
#include <stdint.h>

void decipher(unsigned int num_rounds,uint32_t v[2],uint32_t const key[4]){
        unsigned int i;
        uint32_t v0 = v[0], v1 = v[1], delta = 0x78955381, sum = delta * -num_rounds;
        for(i = 0; i < num_rounds; i++){
        v1 -= (((v0 << 3) ^ (v0 >> 6))+v0) ^ (sum + key[(sum >> 11) & 3]);
        sum += delta;
        v0 -= (((v1 << 3) ^ (v1 >> 6)) + v1) ^ (sum + key[sum & 3]);
        } 
        v[0] = v0; v[1] = v1;
}

uint8_t rebits(uint8_t n)
{
        uint8_t count = 0;
        for(int i = 0; i < 8; i++)
        {
                count = count *2 + n % 2;                 
                n /= 2;
//超简便的 bit 逆序算法, + n % 2 就是取 8 bit 最后一位,搭配  *2 就是从 0 开始不断把最后一位往前移动,n / 2 是无余数的也就是不断舍弃最后一位 
        }
        return count;
}

 int main(){
        uint8_t enc[]={0x72, 0x0C, 0xF6, 0x0E, 0x8C, 0x69, 0x23, 0x69, 0x59, 0xA8, 0x06, 0xEF, 0x2A, 0x1A, 0x56, 0xB6, 0x96, 0xAC, 0xEE, 0x92,0x5C, 0xF2, 0xED, 0x0A, 0x5F, 0x36, 0x8E, 0x41, 0xA6, 0x36, 0x86, 0x72, 0x56, 0xD2, 0x54, 0xC2, 0x00, 0xC8, 0xA8, 0x00};
    uint8_t key1[33] = "Welcome to the g";                                                        //适用于 IDA 单 bit 或字符串取数 
    uint8_t key2[32] = "ame!\nYour key: ";                
        unsigned int r=12;                                //这里是加密轮数,自己设置 
        decipher(r,(uint32_t *)(enc+4),(const uint32_t *)key1);                        //适用于 IDA 单个 bit 取数的类型强制转换法 
        decipher(r,(uint32_t *)(enc+20),(const uint32_t *)key2);
        for(int i =0; i < 40; i++)
                enc[i]=rebits(enc[i]);
        printf("%s",enc);
        return 0;
}

在这里插入图片描述
.
.
在这里插入图片描述

参考博客:
http://blog.leanote.com/post/xp0int/2022-%E5%B9%BF%E4%B8%9C%E7%9C%81%E5%A4%A7%E5%AD%A6%E7%94%9F%E7%BD%91%E7%BB%9C%E6%94%BB%E9%98%B2%E5%A4%A7%E8%B5%9B%E9%83%A8%E5%88%86#p-4

re.zip

140.33 KB, 下载次数: 49, 下载积分: 吾爱币 -1 CB

免费评分

参与人数 46威望 +2 吾爱币 +140 热心值 +39 收起 理由
ccjxtzz + 1 我很赞同!
windpeaceflowe + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
haopeiyou + 1 已经处理,感谢您对吾爱破解论坛的支持!
wivae + 1 + 1 我很赞同!
wasyg + 1 + 1 用心讨论,共获提升!
Jackbboy + 1 + 1 我很赞同!
Randyguo + 1 + 1 我很赞同!
VivianDawson233 + 1 鼓励转贴优秀软件安全工具和文档!
Conight + 1 + 1 我很赞同!
soyiC + 1 + 1 热心回复!
aideyiyi + 1 + 1 我很赞同!
15119464068 + 1 我很赞同!
yangyou719 + 1 + 1 虽然我看不懂,但觉得很厉害的样子
fz52033 + 1 用心讨论,共获提升!
blindcat + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
pandore + 1 + 1 我很赞同!
nightmare77 + 1 + 1 热心回复!
fjyuxin + 1 + 1 我很赞同!
yazhou098 + 1 用心讨论,共获提升!
Radiumlrb + 1 + 1 我很赞同!
黑猫永不败北 + 1 + 1 用心讨论,共获提升!
哇卡s + 1 + 1 热心回复!
Flytom + 1 + 1 热心回复!
404undefined + 1 + 1 我很赞同!
jackies + 1 + 1 用心讨论,共获提升!
235956 + 1 + 1 谢谢@Thanks!
azcolf + 1 + 1 热心回复!
ZHHua + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
TonyKing + 1 大佬太强了
17606004414 + 1 + 1 谢谢@Thanks!
duck007 + 1 热心回复!
EulerNN + 1 + 1 我很赞同!
yangchen520 + 1 热心回复!
yixi + 1 + 1 谢谢@Thanks!
time2s + 1 + 1 我很赞同!
s3nake + 1 我很赞同!
seei + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
fengbolee + 2 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
独行风云 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
努力加载中 + 1 + 1 谢谢@Thanks!
天空宫阙 + 2 + 1 用心讨论,共获提升!
永恒与时光 + 1 我很赞同!
吾之名翎 + 1 我很赞同!
Long0296 + 1 鼓励转贴优秀软件安全工具和文档!
heimaojingzhang + 1 + 1 用心讨论,共获提升!
Hmily + 2 + 100 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| muyilin 发表于 2022-6-2 11:27
卢瑟福瓜皮 发表于 2022-6-2 11:24
TQL,师傅有MISC的题目吗

没有耶,MISC方向不是我负责
immortal23 发表于 2022-10-23 23:59
@muyilin    没想到我出的题居然用在了广东省赛里了  师傅很厉害呀   我给师傅贴个源码好吧

[C++] 纯文本查看 复制代码
&#65279;#include <iostream>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#include <string>
#include <windows.h>
#include <Memoryapi.h>
#include<SIGNAL.H>
#include <process.h>
using namespace std;
#define FLAGLENGTH 36
#define SECNAME ".CRT$XCG"
#pragma section(SECNAME,long,read)

//uint8_t flag[FLAGLENGTH + 1] = "N0opa_G3Ey#zTXjmi5wIHd&5pRN2elaNjK*C";
uint8_t flag[FLAGLENGTH + 1];
uint8_t* pflag;
uint8_t bytes[] = {
	39, 68, 127, 235, 58, 143, 26, 46, 251, 65, 230, 70, 251, 89, 238, 66, 251, 73, 214, 70, 249, 73, 238, 133, 114, 133, 179, 246, 58, 135, 179, 22, 249, 76, 242, 135, 55, 248, 49, 75, 130, 12, 246, 14, 114, 203, 179, 226, 13, 160, 156, 137, 181, 73, 10, 14, 114, 12, 246, 133, 55, 240, 205, 75, 98, 3, 117, 138, 114, 12, 246, 133, 55, 248, 123, 26, 183, 12, 246, 14, 114, 135, 179, 250, 179, 228, 240, 63, 176, 135, 179, 250, 115, 206, 125, 75, 130, 143, 22, 13, 58, 129, 250, 139, 114, 12, 246, 14, 58, 135, 179, 46, 58, 13, 62, 133, 122, 135, 179, 254, 115, 196, 199, 222, 115, 73, 14, 133, 55, 224, 247, 75, 130, 135, 179, 246, 255, 24, 51, 14, 114, 12, 246, 133, 55, 244, 55, 230, 116, 61, 52, 133, 55, 244, 247, 204, 249, 73, 6, 207, 154, 7, 127, 206, 241, 236, 245, 70, 255, 0, 115, 14, 114, 12, 246, 70, 249, 73, 214, 70, 115, 196, 125, 6, 249, 73, 6, 15, 186, 61, 38, 15, 55, 248, 117, 75, 142, 13, 31, 126, 141, 243, 9, 70, 249, 73, 238, 133, 39, 244, 127, 30, 58, 135, 179, 22, 58, 143, 54, 10, 249, 89, 2, 135, 98, 156, 190, 141, 182, 44, 171, 205
}; //put code here
DWORD protect = PAGE_READWRITE; 
uint8_t info[] = { 155, 169, 160, 175, 163, 161, 169, 236, 184, 163, 236, 184, 164, 169, 236, 171, 173, 161, 169, 237, 198, 149, 163, 185, 190, 236, 167, 169, 181, 246, 236 };
uint8_t cmp[] = { 114, 12, 246, 14, 0x8c, 0x69, 0x23, 0x69, 0x59, 0xa8, 0x06, 0xef, 0x2a, 0x1a, 0x56, 0xb6, 0x96, 0xac, 0xee, 0x92, 0x5c, 0xf2, 0xed, 0x0a, 0x5f, 0x36, 0x8e, 0x41, 0xa6, 0x36, 0x86, 0x72, 0x56, 0xd2, 0x54, 0xc2, 0x00, 0xc8, 0xa8, 0x00, };
void* meth;
HANDLE hThread = NULL;
unsigned threadID;
typedef NTSTATUS(NTAPI *pfnNtSetInformationThread)(
	_In_ HANDLE ThreadHandle,
	_In_ ULONG  ThreadInformationClass,
	_In_ PVOID  ThreadInformation,
	_In_ ULONG  ThreadInformationLength
	);
const ULONG ThreadHideFromDebugger = 0x11;
void HideFromDebugger()
{
	HMODULE hNtDll = LoadLibrary(TEXT("ntdll.dll"));
	pfnNtSetInformationThread NtSetInformationThread = (pfnNtSetInformationThread)
		GetProcAddress(hNtDll, "NtSetInformationThread");
	NTSTATUS status = NtSetInformationThread(GetCurrentThread(),
		ThreadHideFromDebugger, NULL, 0);
}
void before() {
	pflag = (uint8_t*)&hThread-56;
	HANDLE mainThread;
	mainThread = GetCurrentThread();
	SetThreadAffinityMask(mainThread, 0x00000002);
	HideFromDebugger();
}
typedef void(__cdecl *_PVFV)();
__declspec(allocate(SECNAME)) _PVFV dummy[] = { before };
class Base {
public:
	uint8_t* input;
	Base(uint8_t* s) {
		input = s;
	}
	Base() {
		if (IsDebuggerPresent())
		{
			exit(-1);
		}
		CONTEXT ctx = {};
		ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
		if (GetThreadContext(GetCurrentThread(), &ctx))
		{
			if (ctx.Dr0 != 0 || ctx.Dr1 != 0 || ctx.Dr2 != 0 || ctx.Dr3 != 0)
			{
				exit(-1);
			}
		}
	}
	virtual void imple() {
		for (int i = 0; i < FLAGLENGTH; i++) {
			input[i] = ((input[i] & 0xaa) >> 0x1) | ((input[i] & 0x55) << 0x1);
			input[i] = ((input[i] & 0xcc) >> 0x2) | ((input[i] & 0x33) << 0x2);
			input[i] = ((input[i] & 0xf0) >> 0x4) | ((input[i] & 0xf) << 0x4);
		}
	}
};
class DeCrypt : public virtual Base
{
public:
	DeCrypt(uint8_t* s) {
		input = s;
	}
	DeCrypt() {}
	virtual void imple() {
		int size = sizeof(bytes);
		meth = VirtualAlloc(NULL, size, MEM_COMMIT, protect);
		uint8_t* write = (uint8_t*)meth;
		for (int i = 0; i < size; i++) {
			write[i] = bytes[i] ^ input[i%4];
		}
		VirtualProtect(meth, size, PAGE_EXECUTE_READ, &protect);
		
	}
};

unsigned __stdcall  checkdebug(void* pArguments) {
	while (true) {
		for (int i = 0; i < sizeof(bytes); i++) {
			if (*((uint8_t*)meth+i) == 0xcc ) {
				exit(-1);
			}
		}
	}
	return 0;
}
class Exec : public virtual Base
{
public:
	Exec(){
		this->imple();
	}
	virtual void exec() {
		typedef void(*fptr)(unsigned int, uint32_t*, uint32_t*);
		fptr my_fptr = reinterpret_cast<fptr>(reinterpret_cast<uint64_t>(meth));
		uint8_t info[] = "Welcome to the game!\nYour key: ";
		my_fptr(12, (uint32_t*)&input[4], (uint32_t*)&info[0]);
		my_fptr(12, (uint32_t*)&input[20], (uint32_t*)&info[16]);
	}

	virtual void imple() {
		hThread = (HANDLE)_beginthreadex(NULL, 0, checkdebug, &bytes, 0, &threadID);
		SetThreadAffinityMask(hThread, 0x00000001);
		Sleep(100);
	}
};

void real_cmp() {
	uint8_t success[] = { 6, 32, 102, 54, 48, 96, 38, 123 };
	if (!strncmp((char*)cmp, (char*)pflag, FLAGLENGTH)) {
		for (auto c : success) {
			printf("%c",c^0x55);
		}
	}
}
class Fin : public Exec, public DeCrypt {
public:
	Fin(uint8_t* s) {
		input = s;
		uint64_t* pVirtualFunctionTable = (uint64_t*)*((uint64_t*)this + 4);
		DWORD old;
		//修改内存属性
		VirtualProtect(pVirtualFunctionTable, 4, PAGE_READWRITE, &old);
		pVirtualFunctionTable[0] = (uint64_t)real_cmp;
		VirtualProtect(pVirtualFunctionTable, 4, old, &old);
	}
	void imple() { 
		uint8_t success[] = { 6, 32, 102, 54, 48, 96, 38, 123 };
		if (!strncmp((char*)cmp+4, (char*)input, FLAGLENGTH)) {
			for (auto c : success) {
				printf("%c", c ^ 0x55);
			}
		}
	}
};

int main() {
	cout << "Welcome to the game!\nYour key: ";
	scanf_s("%s", (char*)flag, FLAGLENGTH+1);
	if (strlen((char*)flag) != FLAGLENGTH) {
		exit(0);
	}
	Base* base = new Base(flag);
	base->imple();
	delete[] base;
	DeCrypt* dec = new DeCrypt(flag);
	dec->imple();
	delete[] dec;
	Fin* fin = new Fin(flag);
	fin->exec();
	fin->imple();
	delete[] fin;

}
 楼主| muyilin 发表于 2022-6-2 10:09
卢瑟福瓜皮 发表于 2022-6-2 11:24
TQL,师傅有MISC的题目吗
oksuqianyu 发表于 2022-6-2 16:50
总是学习,还会突破不了自己屌瓶颈
oksuqianyu 发表于 2022-6-2 16:51
什么时候搞一种算法只能自己能跑就厉害了。
sojurice 发表于 2022-6-2 20:37
感谢分享!
Jackamy 发表于 2022-6-2 23:47
学习学习再学习。基础差看不懂
GuiXiaoQi 发表于 2022-6-3 07:16
有没有安卓逆向的
铁狼 发表于 2022-6-3 08:36
涨知识勒,C语言yyds
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-27 00:36

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表