1.藏在ezbypass中的base.exe逆向题
逆向攻防分析:
逆向的目标类型:
逆向的防御技术:去除程序符号表
flag加密手段:RC4流密码 && base64换表
涉及的算法与数据结构:
逆向的对抗技术:
逆向分析中的问题:
获得flag:
解出的flag:flag{Ez_R3veR2e_w1Th_RC$_4nd_bAsE64}
题目信息:
简介:
wp借鉴:
程序预运行:
在ezbypass中的hint.zip中发现.jar文件
解压之后相当于一个文件夹,发现一个exe, base.exe
D:\CTF_STUDY\CTF比赛\湖南省省赛2024曙光杯\题目附件\EZBYPASS\EZBYPASS-0.0.1-SNAPSHOT - 副本
├─BOOT-INF
│ │ classpath.idx
│ │ layers.idx
│ │
│ ├─classes
│ │ │ application.properties
│ │ │ base.exe
│ │ │ base.exe.i64
│ │ │
│ │ └─com
│ │ └─example
│ │ └─ezbypass
│ │ │ EzbypassApplication.class
....
输入:
flag{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
核心伪代码分析:
整体代码逆向分析:
整体分析:
int __cdecl main(int argc, const char **argv, const char **envp)
{__int64 idx; // raxunsigned __int64 len; // [rsp+38h] [rbp-A0h] BYREFchar input_en[152]; // [rsp+40h] [rbp-98h] BYREF__main_0(argc, argv, envp);printf("your flag:\n");scanf("%s", input);if ( ~(strlen(input) + 1) == -38i64 ){base64(input_en, 0x80ui64, &len, input, 0x24ui64);// 可以很轻松的看见base64加密,且换表了if ( len == 0x30 ){en1(S_box, "ezezrevssefesfawf", 12u); // 这个函数生产出一个S_box数组en2(S_box, input_en, 0x30); // 将S_box传入作为KeyStream,进行rc4加密idx = 0i64;while ( input_en[idx] == target[idx] ) // 对比结果{if ( ++idx == '0' ){printf("you are right!\n");return 0;}}}}return 0;
}
分析:
提取出target数据:
[0x4E, 0x07, 0xEA, 0xDA, 0x72, 0xF2, 0xC7, 0x2A, 0x35, 0x85, 0x76, 0x6C, 0xE8, 0x68, 0x0E, 0x6D, 0xF8, 0x3E, 0xBF, 0x16, 0x82, 0xB3, 0x11, 0x56, 0x27, 0x71, 0x59, 0x59, 0xE6, 0x01, 0x5B, 0x63, 0x26, 0xE1, 0x4B, 0x3D, 0xF8, 0x25, 0x08, 0x85, 0xBE, 0xF5, 0x5D, 0x97, 0x73, 0xB6, 0x39, 0xAF]
直接丢进ida进行分析:
分析en1函数:
__int64 __fastcall sub_4016D2(_BYTE *a1, unsigned __int8 *a2, unsigned int a3)
{__int64 v3; // r9int *v4; // rdi__int64 i; // rcx__int64 v7; // rbx__int64 v8; // rdi__int64 v9; // rdx__int64 result; // raxint v11[266]; // [rsp+20h] [rbp-428h] BYREFv3 = 0i64;v4 = v11;for ( i = 256i64; i; --i )*v4++ = 0;do{a1[v3] = v3;v11[v3] = a2[v3 % a3];++v3;}while ( v3 != 0x100 );*a1 = 0;v7 = 0i64;LODWORD(v8) = 0;v11[0] = *a2;do{v8 = ((v11[v7] + v8 + a1[v7]) % 256);v9 = v7++;result = (sub_4016BC)(a1, v9, v8);}while ( v7 != 0x100 );return result;
}
直接丢给gpt来分析,提示词:“这是一个加密算法大胆的猜测和重新更换变量名让我更好的理解”:
__int64 __fastcall key_schedule(_BYTE *state, unsigned __int8 *key, unsigned int key_length)
{__int64 i; // 当前索引int *temp_buffer; // 临时数组,用于存储密钥调度的中间状态__int64 j; // 计数变量,用于密钥调度__int64 swap_index; // 交换的索引__int64 temp_value; // 中间交换值__int64 result; // 最终返回结果int buffer[266]; // 临时存储密钥的扩展值(未使用完的部分)// 初始化状态数组和临时数组i = 0i64;temp_buffer = buffer;for (__int64 k = 256i64; k; --k)*temp_buffer++ = 0;// 初始化state和temp_bufferdo{state[i] = i; // 初始化state数组为[0, 1, 2, ..., 255]buffer[i] = key[i % key_length]; // 将密钥扩展填充到临时数组buffer中++i;}while (i != 0x100); // 循环256次,state和buffer完成初始化// 初始化状态变量state[0] = 0; j = 0i64; // j是交换索引temp_value = 0; // temp_value作为中间变量buffer[0] = *key; // 使用密钥的第一个字节初始化buffer[0]// 进行密钥调度算法do{temp_value = (buffer[j] + temp_value + state[j]) % 256; // 计算交换索引swap_index = j++; // 增加计数result = swap_values(state, swap_index, temp_value); // 调用子函数交换state中的两个值}while (j != 0x100); // 完成256次交换return result;
}
这个函数只传入了一个State也就算产生一个S盒,每次都一样,所以直接动态调试提取出来:
[0x3E, 0xE0, 0x60, 0x0F, 0x3A, 0xA4, 0x6C, 0x5A, 0x15, 0xCA, 0xF3, 0x69, 0xD4, 0x5B, 0x24, 0xC1, 0x55, 0x41, 0xD7, 0x5C, 0xE4, 0xAD, 0x1B, 0xE3, 0xDB, 0x59, 0x02, 0x39, 0x06, 0x7D, 0x4F, 0xA3, 0xFB, 0xA2, 0x2A, 0x56, 0x29, 0xDA, 0x88, 0x20, 0x52, 0x0E, 0x4C, 0x33, 0x61, 0x95, 0x9D, 0xB8, 0x4D, 0xC5, 0x8F, 0x48, 0xE2, 0xE1, 0xC2, 0xA7, 0x12, 0x08, 0x85, 0xE7, 0xA6, 0x32, 0x81, 0xB9, 0x11, 0x1E, 0x93, 0x7F, 0xA8, 0xF5, 0x8C, 0xF1, 0xA1, 0xF8, 0x45, 0xC0, 0x0B, 0xB0, 0x21, 0x2D, 0x2C, 0x7B, 0x36, 0x58, 0x74, 0x68, 0xB2, 0x8E, 0x80, 0xF4, 0x03, 0x96, 0x7A, 0xDF, 0x79, 0x13, 0x47, 0xDD, 0x05, 0x8D, 0x9A, 0x97, 0xDC, 0x09, 0xD9, 0xDE, 0x90, 0xF6, 0x77, 0x73, 0x6E, 0x6B, 0x98, 0x46, 0xCF, 0xFC, 0x99, 0x3B, 0xEC, 0xC8, 0x4B, 0x38, 0x5D, 0x70, 0x30, 0x84, 0xAF, 0x92, 0x76, 0x65, 0xC7, 0x23, 0xBB, 0x4E, 0xE6, 0xE5, 0xEB, 0xBA, 0x89, 0xBE, 0x9F, 0x6A, 0xAC, 0xEE, 0x14, 0xAA, 0x78, 0xC9, 0xBD, 0xE8, 0x07, 0x43, 0x42, 0x2E, 0xA0, 0xB3, 0x04, 0x75, 0xF2, 0xF7, 0xB1, 0xB7, 0xBC, 0x53, 0x3D, 0x19, 0x64, 0xD2, 0x0D, 0x28, 0xB5, 0xB6, 0x50, 0x51, 0x6D, 0xBF, 0x31, 0xFA, 0x94, 0xCD, 0xD0, 0x71, 0x16, 0x1A, 0xC3, 0xA9, 0x3F, 0x1D, 0xF9, 0x8A, 0x2F, 0x18, 0x0C, 0xD6, 0x44, 0x25, 0x2B, 0x9E, 0x67, 0xAB, 0x27, 0x10, 0x83, 0xAE, 0x82, 0x00, 0x54, 0x34, 0xB4, 0xEA, 0x35, 0xC6, 0xA5, 0x1C, 0xFE, 0x5E, 0x22, 0xCB, 0x86, 0xD3, 0xF0, 0xC4, 0x63, 0x91, 0xEF, 0x26, 0x87, 0xE9, 0x62, 0x1F, 0xCE, 0x8B, 0x6F, 0x9C, 0x7E, 0xCC, 0x4A, 0x40, 0x5F, 0x37, 0x66, 0x0A, 0x17, 0xD8, 0xED, 0xFF, 0x7C, 0xD1, 0x72, 0xD5, 0x3C, 0x49, 0xFD, 0x9B, 0x57, 0x01]
分析en2函数:
char __fastcall en2(__int64 sbox, _BYTE *input, int len)
{// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]j = 0;LOBYTE(idx) = 0;start_addr = input;end = &input[len];while ( start_addr != end ){idx = (idx + 1);S_i = *(sbox + idx);sum = (S_i + j);S_sum = *(sbox + (S_i + j)) + S_i;j = sum;swap_index = S_sum;swap_values(sbox, idx, sum);key_byte = *(sbox + swap_index);*start_addr++ ^= key_byte;}return key_byte;
}
加密手段:这里很轻松的可以看出是rc4加密!
数据结构分析:
逆向分析中的问题:
所以加密方式出来了也就只剩下解密脚本了:base64+rc4
脚本:
解密脚本:
import base64
class RC4Encryptor:def __init__(self):self.size = 256 # S 盒大小self.sbox = [0x3E, 0xE0, 0x60, 0x0F, 0x3A, 0xA4, 0x6C, 0x5A, 0x15, 0xCA, 0xF3, 0x69, 0xD4, 0x5B, 0x24, 0xC1, 0x55, 0x41, 0xD7, 0x5C, 0xE4, 0xAD, 0x1B, 0xE3, 0xDB, 0x59, 0x02, 0x39, 0x06, 0x7D, 0x4F, 0xA3, 0xFB, 0xA2, 0x2A, 0x56, 0x29, 0xDA, 0x88, 0x20, 0x52, 0x0E, 0x4C, 0x33, 0x61, 0x95, 0x9D, 0xB8, 0x4D, 0xC5, 0x8F, 0x48, 0xE2, 0xE1, 0xC2, 0xA7, 0x12, 0x08, 0x85, 0xE7, 0xA6, 0x32, 0x81, 0xB9, 0x11, 0x1E, 0x93, 0x7F, 0xA8, 0xF5, 0x8C, 0xF1, 0xA1, 0xF8, 0x45, 0xC0, 0x0B, 0xB0, 0x21, 0x2D, 0x2C, 0x7B, 0x36, 0x58, 0x74, 0x68, 0xB2, 0x8E, 0x80, 0xF4, 0x03, 0x96, 0x7A, 0xDF, 0x79, 0x13, 0x47, 0xDD, 0x05, 0x8D, 0x9A, 0x97, 0xDC, 0x09, 0xD9, 0xDE, 0x90, 0xF6, 0x77, 0x73, 0x6E, 0x6B, 0x98, 0x46, 0xCF, 0xFC, 0x99, 0x3B, 0xEC, 0xC8, 0x4B, 0x38, 0x5D, 0x70, 0x30, 0x84, 0xAF, 0x92, 0x76, 0x65, 0xC7, 0x23, 0xBB, 0x4E, 0xE6, 0xE5, 0xEB, 0xBA, 0x89, 0xBE, 0x9F, 0x6A, 0xAC, 0xEE, 0x14, 0xAA, 0x78, 0xC9, 0xBD, 0xE8, 0x07, 0x43, 0x42, 0x2E, 0xA0, 0xB3, 0x04, 0x75, 0xF2, 0xF7, 0xB1, 0xB7, 0xBC, 0x53, 0x3D, 0x19, 0x64, 0xD2, 0x0D, 0x28, 0xB5, 0xB6, 0x50, 0x51, 0x6D, 0xBF, 0x31, 0xFA, 0x94, 0xCD, 0xD0, 0x71, 0x16, 0x1A, 0xC3, 0xA9, 0x3F, 0x1D, 0xF9, 0x8A, 0x2F, 0x18, 0x0C, 0xD6, 0x44, 0x25, 0x2B, 0x9E, 0x67, 0xAB, 0x27, 0x10, 0x83, 0xAE, 0x82, 0x00, 0x54, 0x34, 0xB4, 0xEA, 0x35, 0xC6, 0xA5, 0x1C, 0xFE, 0x5E, 0x22, 0xCB, 0x86, 0xD3, 0xF0, 0xC4, 0x63, 0x91, 0xEF, 0x26, 0x87, 0xE9, 0x62, 0x1F, 0xCE, 0x8B, 0x6F, 0x9C, 0x7E, 0xCC, 0x4A, 0x40, 0x5F, 0x37, 0x66, 0x0A, 0x17, 0xD8, 0xED, 0xFF, 0x7C, 0xD1, 0x72, 0xD5, 0x3C, 0x49, 0xFD, 0x9B, 0x57, 0x01]def enc_dec(self, data: bytes) -> bytes:"""使用 RC4 算法对数据进行加解密 (加密和解密过程相同):param data: 明文数据 (或密文数据) 的字节形式:return: 加密后的密文 (或解密后的明文)"""j = 0k = 0result = bytearray()for i in range(len(data)):j = (j + 1) % self.sizek = (k + self.sbox[j]) % self.size# 交换 sbox[j] 和 sbox[k]self.sbox[j], self.sbox[k] = self.sbox[k], self.sbox[j]# 生成伪随机字节 RR = self.sbox[(self.sbox[j] + self.sbox[k]) % self.size]# 加密/解密当前字节result.append(data[i] ^ R)return bytes(result)# 示例使用
if __name__ == "__main__":# 实例化加密器rc4 = RC4Encryptor()ciphertext = [0x4E, 0x07, 0xEA, 0xDA, 0x72, 0xF2, 0xC7, 0x2A, 0x35, 0x85, 0x76, 0x6C, 0xE8, 0x68, 0x0E, 0x6D, 0xF8, 0x3E, 0xBF, 0x16, 0x82, 0xB3, 0x11, 0x56, 0x27, 0x71, 0x59, 0x59, 0xE6, 0x01, 0x5B, 0x63, 0x26, 0xE1, 0x4B, 0x3D, 0xF8, 0x25, 0x08, 0x85, 0xBE, 0xF5, 0x5D, 0x97, 0x73, 0xB6, 0x39, 0xAF]# 解密数据(同样的 enc_dec 函数可以用于解密)decrypted_data = rc4.enc_dec(ciphertext)print("解密后的明文:", decrypted_data.decode("utf-8"))enstr = decrypted_data.decode("utf-8")string1 = "abcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZ"string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"a=enstr.translate(str.maketrans(string1,string2))#利用密码表还原成正常base64编码后的字符串print(base64.b64decode(a).decode())#base64解码
2.PPT 获取密码
所涉及的工具和知识
Mimikatz猕猴桃工具
windows中的lsass.exe
压缩包密码爆破工具
die(PE分析工具)
010 Editor(二进制编辑工具)
压缩包密码爆破工具:
ZongXR/Archive-password-cracker: 设计精良的压缩包密码破解工具,具有自定义字典、导出字典、选择字典等功能。基于Python实现,支持多线程与多进程,不断完善中…… (github.com)
解题过程
这是一个藏在靶机的彩蛋:
可以通过代码审计找出来!!!
下载得到pptx.zip!!
打开后可以发现问题,ppt太大了!一定存在附件:
使用DIE来提取分离附件:
提取出zip压缩包,发现里面存在一个其他的东西:
存在文件:手高是的念来过倒
发现这是个二进制文件,丢进010editor看看
发现一个到的字符串weakpassword
最后还发现一个KP文件头这是一个zip压缩包!
很显然正文件都杯倒转了,写个python脚本倒置一下就可以了!
import structdef reverse_binary_file(file_path):# 读取原始二进制文件with open(file_path, 'rb') as file:content = bytearray(file.read())# 反转字节序列reversed_content = content[::-1]# 写入新的反转后的文件new_file_path = f"{file_path}_reversed"with open(new_file_path, 'wb') as new_file:new_file.write(reversed_content)print(f"原始文件已成功反转并保存为 {new_file_path}")reverse_binary_file("手高是的念来过倒")
成功解出:
但是这个压缩包存在密码通过前面的提示是weakpassword,所以是一个可以爆破出来的密码直接上工具:爆破出来密码是:2233
压缩包里面放了一个lsass.dmp是一个windows的系统文件可以解密出Windows的用户密码!,直接上工具
【内网渗透】神器Mimikatz的入门简单实践-腾讯云开发者社区-腾讯云 (tencent.com)
lsass.dmp就可以被提取出密码了!
E:\ReverseTools\mimikatz_trunk\x64>Mimikatz.exe.#####. mimikatz 2.2.0 (x64) #19041 Aug 10 2021 17:19:53.## ^ ##. "A La Vie, A L'Amour" - (oe.eo)## / \ ## /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )## \ / ## > https://blog.gentilkiwi.com/mimikatz'## v ##' Vincent LE TOUX ( vincent.letoux@gmail.com )'#####' > https://pingcastle.com / https://mysmartlogon.com ***/mimikatz # sekurlsa::minidump
Switch to MINIDUMP : ERROR kuhl_m_sekurlsa_minidump ; <minidumpfile.dmp> argument is missingmimikatz # sekurlsa::minidump D:\CTF_Study\CTF比赛\湖南省省赛2024曙光杯\ppt\解析文件\lsass.dmp
Switch to MINIDUMP : 'D:\CTF_Study\CTF±ÈÈü\ºþÄÏʡʡÈü2024Êï¹â±\ppt\½âÎöÎļþ\lsass.dmp'mimikatz # sekurlsa::minidump E:\ReverseTools\mimikatz_trunk\x64\lsass.dmp
Switch to MINIDUMP : 'E:\ReverseTools\mimikatz_trunk\x64\lsass.dmp'mimikatz # sekurlsa::logonpasswords
Opening : 'E:\ReverseTools\mimikatz_trunk\x64\lsass.dmp' file for minidump...Authentication Id : 0 ; 152099 (00000000:00025223)
Session : Interactive from 1
User Name : cloud
Domain : WIN-O632B9H1O1C
Logon Server : WIN-O632B9H1O1C
Logon Time : 2024/5/17 23:46:57
SID : S-1-5-21-386290112-873935545-3080084739-1000msv :[00000003] Primary* Username : cloud* Domain : WIN-O632B9H1O1C* NTLM : 59133f168874bcb04289879eb65e7b85* SHA1 : 90f9ad6f10d4cf67c82b2b89869b64f03f59d3f8tspkg :* Username : cloud* Domain : WIN-O632B9H1O1C* Password : flag{45cc90d8-3048-18fd-b97b-a959dee2ddb3}wdigest :* Username : cloud* Domain : WIN-O632B9H1O1C* Password : flag{45cc90d8-3048-18fd-b97b-a959dee2ddb3}kerberos :* Username : cloud* Domain : WIN-O632B9H1O1C* Password : flag{45cc90d8-3048-18fd-b97b-a959dee2ddb3}ssp :credman :Authentication Id : 0 ; 152055 (00000000:000251f7)
Session : Interactive from 1
User Name : cloud
Domain : WIN-O632B9H1O1C
Logon Server : WIN-O632B9H1O1C
Logon Time : 2024/5/17 23:46:57
SID : S-1-5-21-386290112-873935545-3080084739-1000msv :[00000003] Primary* Username : cloud* Domain : WIN-O632B9H1O1C* NTLM : 59133f168874bcb04289879eb65e7b85* SHA1 : 90f9ad6f10d4cf67c82b2b89869b64f03f59d3f8tspkg :* Username : cloud* Domain : WIN-O632B9H1O1C* Password : flag{45cc90d8-3048-18fd-b97b-a959dee2ddb3}wdigest :* Username : cloud* Domain : WIN-O632B9H1O1C* Password : flag{45cc90d8-3048-18fd-b97b-a959dee2ddb3}kerberos :* Username : cloud* Domain : WIN-O632B9H1O1C* Password : flag{45cc90d8-3048-18fd-b97b-a959dee2ddb3}ssp :credman :