Xunflash的小站 - CTF
type: channel
link: https://xunflash.top/category/CTF/
items: 【Reverse】2023浙江省大学生网络安全技能竞赛预赛WriteUp
items: 【CTF】Rust逆向，BeingDebugged，异或取表算法逆向 内存取证 2023上海市赛初赛
items: 【逆向学习】Windows平台下的DLL注入
items: 【CTF】Reverse Writeup Win API逆向，Python字节码 OLLVM，rc4 换表base64 2022DASCTF Oct 逆向学习
items: 【CTF】Reverse Writeup TracerPid反调试，BUG()内核异常 2022长城杯决赛 逆向学习
items: 【CTF】Reverse Writeup 魔改tea，smc加密与验证 2022hws 逆向学习
items: 【CTF】Reverse Writeup babynim 蓝帽杯复赛 逆向学习
items: 【CTF】Reverse Writeup deeprev+GameMaster等 强网杯 逆向学习
items: 【CTF】IDA for RE 插件推荐
items: 【CTF】Reverse LOADER pell方程 nim-lang 蓝帽杯 逆向学习

【Reverse】2023浙江省大学生网络安全技能竞赛预赛WriteUp
type: item
date: 2023-11-07T10:04:50+00:00
description: 好像好久好久没更新博客了，水一篇WP好了排名4AK了逆向 多亏了@woodwhale教我lua，不然歇逼了题目没啥难度，就是老喜欢自己写算法挺恶心人的。pycccpycdc直接出代码，异或脚本即可check = [ 102, 109, 99, 100, 127, 52, 114, 88, 97, 122, 85, 125, 105, 127, 119, 80, 120, 112, 98, 39, 109, 52, 55, 106] for i in range(len(check)): print(chr(check[i] ^ i),end='') luare断点到000055C07F31848C可以搜内存搜到\x1bLua，dump出来binary形式的lua脚本 用unluac即可反编译出来，可以看到调用了Oo00Oo0Oo00Oo0是一个取表替换的算法，写脚本解密即可lines = '''0x60856D1028C8953C 0x964849764CB30359 0x2E7164C479B75FB8 0x80637291A7AC8C38 0x7B8BF3AE4B339EB0 0xCFE06FEC52B45B4D 0x5DC67EAAB20C3AD 0x24FCFBD656409F00 0x4AF00D463D0BCA92 0x7DBC8A3B1A11555A 0x3061CE7513A9E76C 0x9C54D007276AA614 0x34C20158D8898E5C 0x50A02AC02F3569E8 0xC0E681D39FF8836 0xB66E7F18FEB1E693 0x29F5D2E92B315378 0x41D9DBDE84172C0F 0x7A45A899A1F71906 0xE5AA0AAF1BA5233E 0x9A3A82FAF8E1A4EF 0xC1D173C7651C8FDF 0x8D9DDD875EA2D7C5 0x66EE9790CD81C9F9 0x370874C63F424FDA 0xB93283E32677CB25 0xBA2D4ED544F2D3BD 0xBFE421121E049862 0xA31694FDF486F647 0x430251B27C701FEB 0x5DE26B097ECC1522 0xF157EDD4B5BE9BBB''' from pwn import * global_data = [] def pares(data): x = p64(int(data.strip(), 16)) global_data.extend(list(x)) for l in lines.splitlines(): pares(l.strip()) print(global_data) res = [ 109, -73, -72, 46, -73, -5, 99, -100, 46, 59, 32, -76, 109, 3, 59, 20, -61, -56, -119, 48, 100, 118, 36, 118, 82, 3, 95, 106, 14, -80, 5, -89, 89, -85, 5, 14, 46, -73, 7, 127] flag = '' from ctypes import c_uint8 last = global_data.index(res[-1]) flag += chr(last) for i in range(39): x = -i - 2 last = c_uint8(c_uint8(global_data.index(c_uint8(res[x]).value)).value ^ last).value flag += chr(last) flag = flag[::-1] print(flag)easyapkDES的名，AES的心，main替换了一下key的字符直接cyberchefAndroidELF魔改UPX，改回来就可以unpack中间这个就是加密具体的不截图了，看脚本即可，分别对应四个函数的解密from ctypes import c_uint8 enc = [0x3D, 0x45, 0x38, 0x7E, 0x78, 0x4B, 0x6A, 0x5C, 0x5B, 0x52, 0x4C, 0x73, 0x4E, 0x39, 0x49, 0x5F, 0x49, 0x40, 0x38, 0x5E, 0x74, 0x40, 0x66, 0x44, 0x46, 0x7A, 0x39, 0x3B, 0x67, 0x39, 0x70, 0x6C, 0x71, 0x5E, 0x6D, 0x4D, 0x5A, 0x4C, 0x7F, 0x…

【CTF】Rust逆向，BeingDebugged，异或取表算法逆向 内存取证 2023上海市赛初赛
type: item
date: 2023-05-22T17:49:00+00:00
description: 上海市赛初赛两个简单题拿了三血，还摸了两题Misc，最开始比赛没沉下心还是浪费了一些时间，感觉应该能更好的。近期来打的比较爽的一次比赛。两题逆向都0解，后面也没深究了...感觉不如MiscReverseexEXE这边一个beingdebugged反调试，noplpAddress里面一个rc4sub_401535是base64，所以就是RC4+base64，直接cyberchef解密就行encrytor大致流程：获取固定的DateTime 16574669，然后获取当前时间，并转换成10进制的Dword数组，获取分钟和秒钟相乘，将获得的数转换为字符串，然后经过SHA256加密，得到的值作为RC4的key对flag.txt进行加密，输出到flag.txt.enc中关键函数：出题时间可以通过文件修改时间查看考虑到程序运行时间，最后取的是33*41=1353rc4解密即可flag在哪？保存了一些函数的地址，重命名一下动调到这里进去p一下，下面call的analyse有问题，nop掉然后看汇编即可可以看到是有一个表，然后nop掉的位置是call了一个memcpy进去的东西看一下Src中间的内容这边也是出题人自己实现的一个算法提取出byte_406274的密文写脚本解密即可enc = [0xD3, 0x38, 0xD1, 0xD3, 0x7B, 0xAD, 0xB3, 0x66, 0x71, 0x3A, 0x59, 0x5F, 0x5F, 0x2D, 0x73] key = 'e4bdtRV02\x00\x00\x00\x00\x00\x00' flagbox = [0x66, 0x6C, 0x61, 0x67, 0x7B, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x6F, 0x6D, 0x7D, 0x00, 0x00, 0x66, 0x6C, 0x61, 0x67, 0x7B, 0x4D, 0x79, 0x20, 0x63, 0x68, 0x65, 0x65, 0x73, 0x65, 0x7D, 0x00, 0x66, 0x6C, 0x61, 0x67, 0x7B, 0x69, 0x20, 0x6D, 0x69, 0x73, 0x73, 0x20, 0x74, 0x6F, 0x6D, 0x7D, 0x00, 0x00, 0x00, 0x00, 0x66, 0x6C, 0x61, 0x67, 0x7B, 0x6C, 0x65, 0x74, 0x27, 0x73, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x61, 0x20, 0x66, 0x75, 0x6E, 0x7D, 0x00, 0x00, 0x66, 0x6C, 0x61, 0x67, 0x7B, 0x75, 0x20, 0x77, 0x61, 0x6E, 0x74, 0x20, 0x73, 0x74, 0x65, 0x61, 0x6C, 0x20, 0x6D, 0x79, 0x20, 0x63, 0x68, 0x65, 0x65, 0x73, 0x65, 0x7D, 0x00, 0x00, 0x00, 0x00, 0x66, 0x6C, 0x61, 0x67, 0x7B, 0x69, 0x20, 0x68, 0x61, 0x76, 0x65, 0x64, 0x20, 0x6C, 0x6F, 0x73, 0x74, 0x20, 0x61, 0x20, 0x63, 0x68, 0x65, 0x65, 0x73, 0x65, 0x7D, 0x00, 0x66, 0x6C, 0x61, 0x67, 0x7B, 0x63, 0x68, 0x65, 0x65, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6D, 0x79, 0x20, 0x6C, 0x69, 0x66, 0x65, 0x7D, 0x00, 0x66, 0x6C, 0x61, 0x67, 0x7B, 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x69, 0x64, 0x20, 0x79, 0x6F, 0x75, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6B, 0x66, 0x61, 0x73, 0x74, 0x7D, 0x00, 0x00, 0x00, 0x66, 0x6C, 0x61, 0x67, 0x7B, 0x6C, 0x65, 0x74, 0x27, 0x73, 0x20, 0x68, 0x61, 0x76, 0x6…

【逆向学习】Windows平台下的DLL注入
type: item
date: 2023-03-14T08:41:11+00:00
description: DLL注入通过DLL注入可以对其他进程进行hook/热补丁/修复BUG，同时也是渗透其他进程的有效方法。DLL被加载到进程后会自动运行DIIMain()函数，用户可以把想执行的代码放到DIIMain()函数，每当加载DLL时，添加的代码就会自然而然得到执行。利用该特性可修复程序Bug，或向程序添加新功能。本篇博客将使用Inline Hook和DLL注入技术实现控制程序执行流DLL注入流程使用MS编译dll动态链接库后，可以通过一些常见的方式进行DLL的注入：创建远程线程（CreateRemoteThread() API）使用注册表（AppInit_DLLs值）消息勾取（SetWindowsHookEx() API）通过这些方法编写注入程序，然后对写有Inline Hook逻辑的DLL程序进行加载并且注入进目标进程代码编写DLL编写DLL加载到进程后会运行DllMain()函数，通过这个特点，我们可以修改上一篇博客中的Inline Hook代码为如下代码其中，DllMain()参数中的ul_reason_for_call与之前TLS_Callback学习博客中的dwReason是相同的。因此，在进程启动的时候我们调用InlineHook()对MessageBoxA()进行hook// dllmain.cpp : 定义 DLL 应用程序的入口点。 #include "pch.h" #include <windows.h> #include <stdio.h> #include <iostream> #include <tchar.h> //修改API入口为 jmp xxx 使得程序能跳转到自己的函数 BYTE __NewCode[7] = { 0xE9, 0x0, 0x0, 0x0, 0x0 }; BYTE __OldCode[7] = { 0 }; FARPROC Messagebox_FARPROC; HMODULE g_hMod; int WINAPI MyMessageBoxA( HWND hWnd, // handle to owner window LPCTSTR lpText, // text in message box LPCTSTR lpCaption, // message box title UINT uType // message box style ); void InlineHook() { DWORD dwOldProtect = 0; //首先获取user32.dll的模块句柄 HMODULE user32_HMODULE = LoadLibraryA("user32.dll"); //利用GetProcAddress获取MessageBoxA导出函数的地址 Messagebox_FARPROC = GetProcAddress(user32_HMODULE, "MessageBoxA"); //利用ReadProcessMemory读取内存中MessageBoxA的前5字节 if (!ReadProcessMemory(GetCurrentProcess(), Messagebox_FARPROC, __OldCode, 6, NULL)) { printf("[!] ReadProcessMemory Failed"); } printf("%x%x%x%x%x\n", __OldCode[0], __OldCode[1], __OldCode[2], __OldCode[3], __OldCode[4]); //E9跳转为jmp地址到目标地址的间隔，地址需要进行计算，计算出来后赋值给newcode的后4位 *((ULONG*)(__NewCode + 1)) = (ULONG)&MyMessageBoxA - ((ULONG)Messagebox_FARPROC + 5); //memcpy(&__NewCode[1], &JmpAddress, 4); printf("JmpAddress : %x\n", *((ULONG*)(__NewCode + 1))); //将权限替换为可读写执行 VirtualProtect(Messagebox_FARPROC, 6, PAGE_EXECUTE_READWRITE, &dwOldProtect); //直接写入内存 WriteProcessMemory(GetCurrentProcess(), Messagebox_FARPROC, __NewCode, 5, NULL); //恢复之前的权限 VirtualProtect(Messagebox_FARPROC, 6, dwOldProtect, &dwOldProtect); } int …

【CTF】Reverse Writeup Win API逆向，Python字节码 OLLVM，rc4 换表base64 2022DASCTF Oct 逆向学习
type: item
date: 2022-10-31T08:32:44+00:00
description: Win API逆向 反调试， Python字节码 ，OLLVM rc4 换表base64贪玩ctfTlsCallback_0有个Isdebuggerpresent反调试 直接nop就行这边messagebox有个小技巧，把中文显示出来，选这个直接显示中文 非常的方便通过中文定位到关键代码发现有个加密 往下翻可以看到可疑加密函数 进入后可以发现频繁调用sbox进行加密操作 并且有两个sbox 猜测为aes 实际动调后发现256字节的两个sbox回到前面先把account解出来acc = [0x04, 0x1F, 0x1F, 0x1E, 0x43, 0x4B, 0x43, 0x45, 0x44, 0x00, 0x16, 0x10, 0x55, 0x17, 0x12, 0x73] for i in range(len(acc)-1): acc[i] ^= acc[15] print(chr(acc[i]), end='') print(chr(acc[15]), end='') #wllm08067sec&das然后拿到密码的密文，这边动调能看到其实是pass的位置。找了一阵子没找到aes的key 但是想着key和account位数好像一致，直接拿去赛博厨子试一下 然后出了flag账号密码拼起来就行pycode队友做的 逆一下字节码然后用z3解就行了from Crypto.Util import number from Crypto.Util.number import * m=b"" from z3 import * def solve(x): a, b, c, d = BitVecs("a b c d", 35) s = Solver() s.add((a >> 11) ^ a == b) s.add(((b << 7) & 0x78866191) ^ b == c) s.add(((c << 15) & 2323163360) ^ c == d) s.add((d >> 18) ^ d == x) an = s.check() print(an) return long_to_bytes(s.model()[a].as_long()^(2**35-1)) enc = "8b2e4e858126bc8478d6a6a485215f03" enc=bytes.fromhex(enc) for i in range(len(enc) // 4): t = enc[i*4:i*4+4] t = number.bytes_to_long(t) m+=solve(t) print(bytes.hex(m))challenge改一下变量名字 断到memset前面可以发现上面一堆是把input的奇数位偶数位单独分开拿出来然后往下看 第一个函数sub4059f0没对input操作 不用管 往下看enc1这个 传了偶数位和sbox进去点进去纯纯的控制流平坦化，D-810一把梭，但是还是很丑（后续发现可能是我d810的插件的z3寄了 没去除完整？）但是看到这个，纯纯的rc4rc4对称加密那直接断点到这个函数前面，然后随便输入点东西，然后用插件把内存里面数据直接改成密文，断点到这个地方，直接看密文即可（不可以断到函数外面，因为下面有引起异常的，程序直接结束了）得到"ACFg0Gw1Jo5Ix9C}"try catch调不了enc2咋整 断点在这个位置直接改eip或者直接nop掉call enc1 让程序直接jmp到catch里面也行但是我们目的根本就不是看enc2是啥 enc2一眼丁真base64换表。目的只是拿到catch块里面换掉的表而已这里有个if，实际调起来会发现会直接退出 那jnz改成jz就行了 暴力一点然后断到这里直接看表即可当然你直接c跑出来表也行 毕竟代码都给了拿到表 直接赛博厨子一把梭最后拼起来就行了a = 'ACFg0Gw1Jo5Ix9C}' b = 'DST{Wo7Xj5Ad8Nx8' flag = '' for i in range(16): flag += b[i] flag += a[i] print(flag)

【CTF】Reverse Writeup TracerPid反调试，BUG()内核异常 2022长城杯决赛 逆向学习
type: item
date: 2022-09-27T09:39:00+00:00
description: 前言长城杯决赛的逆向题目 感觉还是有点意思的 这种读TracerPid的反调试和BUG()内核异常跳转以前没见过 比赛的时候疯狂搜索 也没个解决办法，后来是自己试着调试调试把这个反调试过掉了 然后大概摸清楚了题目的运行逻辑。总的来说这题还是很有趣的。直接看题吧easy_re首先我们拿到题目，进来是start函数，这边可以看到main，init点进去init可以发现加载了三个函数，依次点进去看第一个是一些奇怪的操作，但是可以看到一个函数，这个是检测反调试的第二个是一个TracerPid反调试加BUG（）异常第三个不知道是啥玩意，感觉没啥用经过动态调试，f8断点可以发现程序是先执行init for循环里面的第一个函数，第二个函数，第一个函数里面的那个函数。我们过反调试也很简单，只要在这个位置断点，然后点进cmp左边的，按dddd把里面第一行的pid数字改成0即可然后进入到第一个函数里面的那个函数，这个其实是检测反调试的，之前被卡在这里卡了好久，一直不懂他是怎么传参的，后面发现其实是和之前运行的那个反调试有关系。把反调试过了之后也就进入主函数正常执行了。不过这底下有个函数需要注意，这个是init替换的主函数，实际上这个函数是当成main执行的。点进去看，可以发现有一堆东西，仔细观察汇编可以发现，对用户输入前四位和一些变量进行操作，最后要使得前四个变量值为0，最后可以得到flag。那我们直接用c爆破前四位输入#include<stdio.h> int main(){ int inp[4]; for (int i=30;i<127;i++){ for (int j=30;j<127;j++){ for (int m=30;m<127;m++){ for (int n=30;n<127;n++){ inp[0]=i; inp[1]=j; inp[2]=m; inp[3]=n; int dword_5611F8803040=0; int dword_5611F880303C=0; int dword_5611F8803030=0; int dword_5611F8803034=0; int dword_5611F8803038=0; dword_5611F8803040 += 16; dword_5611F880303C += dword_5611F8803040 * inp[3]; dword_5611F8803040 += 3; dword_5611F880303C += dword_5611F8803040 * inp[2]; dword_5611F8803040 -= 10; dword_5611F8803030 += dword_5611F8803040 * inp[3]; dword_5611F8803040 -= 2; dword_5611F8803034 += dword_5611F8803040 * inp[2]; dword_5611F8803040 += 13; dword_5611F8803030 += dword_5611F8803040 * inp[1]; dword_5611F8803040 -= 8; dword_5611F8803038 += dword_5611F8803040 * inp[1]; dword_5611F8803040 -= 7; dword_5611F8803038 -= 3481; dword_5611F8803040 += 3; dword_5611F8803034 -= 2422; dword_5611F8803040 += 9; dword_5611F8803030 += dword_5611F8803040 * inp[2]; dword_5611F8803040 -= 2; dword_5611F8803038 += dword_5611F8803040 * inp[2]; dword_5611F8803040 -= 6; dword_5611F8803030 -= 4518; dword_5611F8803040 += 7; dword_5611F880303C -= 5006; dword_5611F8803040 -= 9; dword_5611F8803034 += dword_5611F8803040 * inp[0]; dword_5611F8803040 += 5; dword_5611F8803030 += dword_5611F8803040 * inp[0]; dword_5611F8803038 += ++dword_5611F8803040 * inp[0]; dword_5611F8803040 -= 8; dword_5611F8803038 +=…

【CTF】Reverse Writeup 魔改tea，smc加密与验证 2022hws 逆向学习
type: item
date: 2022-08-10T06:21:00+00:00
description: re1直接关键词捕捉Tea 那就是tea加密吧点进tea那个函数里面稍微美化下，可以发现其实是魔改过的xxtea，跑12轮，分了8组。那就直接开逆改一下现成的脚本#include<stdio.h> #include"defs.h" #include <stdint.h> unsigned int enc_2[8] = { 0x10BD3B47, 0x6155E0F9, 0x6AF7EBC5, 0x8D23435F, 0x1A091605, 0xD43D40EF, 0xB4B16A67, 0x6B3578A9 }; unsigned int data[8] = { 0xD58F4C91, 0x9A751121, 0xD1F7D6AC, 0x63575833, 0x2A313023, 0xF9750867, 0xB2A9EDA5, 0xD6A7CD37 }; unsigned int data1[8] = { 0x5DFAFC16, 0x3E3D5252, 0x03623808, 0x6B884FEA, 0xE99A75EB, 0xB741A335, 0x0C77D248, 0xE4908612 }; uint32_t DeryptoLoop(unsigned int num1, unsigned int num2, uint32_t sum, uint32_t index) { unsigned int key[4] = { 0x1234,0x2345,0x4567,0x6789 }; //unsigned int key[4] = { 4,3,2,2 }; uint32_t tmp1 = ((num1 >> 3) ^ 16 * num2) + (4 * num1 ^ (num2 >> 5)); uint32_t tmp2 = (key[(sum >> 2) & 3 ^ index] ^ num2) + (num1 ^ sum); return tmp1 ^ tmp2; } void decrypt2(unsigned dec_2[8]) { unsigned int state[8]; unsigned int DELTA = 0x6a99b4ac; unsigned int key[4] = { 0x1234,0x2345,0x4567,0x6789 }; int round = 0; for (int i = 0; i < 8; i++) { state[i] = enc_2[i]; } int tmpd = DELTA; do { state[7] -= DeryptoLoop(state[0], state[6], tmpd, 3); state[6] -= DeryptoLoop(state[7], state[5], tmpd, 2); state[5] -= DeryptoLoop(state[6], state[4], tmpd, 1); state[4] -= DeryptoLoop(state[5], state[3], tmpd, 0); state[3] -= DeryptoLoop(state[4], state[2], tmpd, 3); state[2] -= DeryptoLoop(state[3], state[1], tmpd, 2); state[1] -= DeryptoLoop(state[2], state[0], tmpd, 1); state[0] -= DeryptoLoop(state[1], state[7], tmpd, 0); tmpd += 0x61C88647; round += 1; } while (round < 12); for (int i = 0; i < 8; i++) { dec_2[i] = state[i]; } } int main(){ unsigned int dec_2[8]; decrypt2(dec_2); for (int i = 0; i < 8; i++) { for (int j = 0; j < 4; j++) { printf("%c", (dec_2[i] >> (j * 8)) & 0xFF); } } //puts(dec_2); //0x33323130, 0x37363534, 0x31303938, 0x35343332, 0x39383736, 0x33323130, 0x37363534, 0x31303938 return 0; }其中有几个要注意的地方，首先就是初始的delta需要动调一下，先动调跑到最后一轮拿到delta然后再拿来解密。然后就是key是异或0123位这样最后得到flag:7f94392…

【CTF】Reverse Writeup babynim 蓝帽杯复赛 逆向学习
type: item
date: 2022-08-10T05:35:00+00:00
description: babynim这题比初赛的简单多了我是没想到的...就是符号表也有，复现了初赛的LOADER之后这题没有难度属于是。ida打开，动态调试到主要逻辑，简单分析，这里验证flag格式分析可以知道star开头的函数进行了乘法，第一个，第二个参数是input与密文1，也就是一串反着的flag(浪费了我的时间。。。，然后第三个参数是结果。eq函数进行了比较，可以把最终的密文提取出来，在hello44里面这里eqeq函数就是对大数进行比较提取数据出来写个python脚本除一下即可得到flagprint(0x1566336316561EDB086701C71C71C7) print(chr(0xa7)) a=0x666C61677B63393461626261652D353263302D346461302D616666312D383839373730353839356337A7 b=0x4732510F4379F99925CF3B2C29EAFA1647B1E897A61BFD7C1D1807478D0E18A1AC9791D6DBB1BD74554FECECC16519CE12AC443DA1877CA8D9 print(b//a) ''' s='7c5985077988-1ffa-0ad4-0c25-eabba49c{galf' ss='' for i in reversed(s): ss+=i print(ss) print(len('c94abbae-52c0-4da0-aff1-8897705895c7')) '''

【CTF】Reverse Writeup deeprev+GameMaster等 强网杯 逆向学习
type: item
date: 2022-08-10T05:29:00+00:00
description: deeprev这题非常新颖，直接在elf里面的LOAD段写机器码，加载汇编并且跳转过去执行最开始其实是常规动调，注意到链接了so文件并且读取了so里面的secret到elf中，那么直接在elf中的secret上面下一个内存读写断点。（这边我给check也下了）然后运行，可以发现载入so库的时候就完成了加密，等到执行到main函数的时候check已经有值了。我自己是通过一直f7步入，ida提示eip跳转到非代码段，从而发现了LOAD段藏起来的机器码。仔细看一下ida的注释就可以发现这边复制了so的secret然后进一步动调加分析可以得到每一片段其实是这样的，每一行第二位是操作码，第一位是偏移地址，第三位是值。动调可以发现有很多重复的这样的片段，并且每一段都把第三行的第三位给第二行的偏移地址，简单理解R_X86_64_RELATIVE，操作码0x8是赋值。在进一步动调之后发现0xc3操作码是标志下一步跳转进LOAD段执行代码那么我们其实只需要把所有的机器码提取出来，再扔到机器码转汇编的网站上面解密就行了。直接复制LOAD段内容，提取机器码s='' with open("qwbre2data","r") as file: for line in file: s+=line[line.find("<"):line.find(">")+1] s+='\n' with open("qwbre2data1","w") as file1: file1.write(s) f=0 with open("qwbre2data1","r") as file2: for line in file2: if "0C3" in line: f=1 continue if f==1: temp=line[line.find(",")+1:] temp1=temp[temp.find(",")+2:temp.find("h")] if len(temp1)>8: if len(temp1)!=16 and len(temp1)>14: temp1=temp1[::-1] temp1+="0" temp1=temp1[::-1] reopcode=temp1 opcode='' for i in reversed(range(0,len(reopcode),2)): opcode+=reopcode[i] opcode+=reopcode[i+1] print(opcode) f=0 ''' 803425CC40800016 800425CC4080 803425CC40800017 800425CC40800001 803425CC40800010 800425CC40800002 803425CC40800012 800425CC40800003 803425CC40800010 800425CC40800004 803425CC40800011 800425CC40800005 803425CC40800012 800425CC40800006 803425CC40800013 800425CC40800007 803425CC40800014 800425CC40800008 803425CC40800015 800425CC40800009 803425CC40800016 800425CC4080000A 803425CC40800017 800425CC4080000B 803425CC40800018 800425CC4080000C 803425CC40800019 800425CC4080000D 803425CC40800024 800425CC4080000E 803425CC4080002C 800425CC4080000F 803425CC40800026 800425CC40800010 803425CC4080001E 800425CC40800011 803425CC4080001F 800425CC40800012 803425CC40800020 800425CC40800013 803425CC40800020 800425CC40800014 803425CC40800021 800425CC40800015 803425CC40800023 800425CC40800016 803425CC40800027 800425CC40800017 803425CC40800024 800425CC40800018 803425CC40800025 800425CC40800019 803425CC40800026 800425CC4080001A 803425CC40800027 800425CC4080001B 80342…

【CTF】IDA for RE 插件推荐
type: item
date: 2022-08-02T07:13:00+00:00
description: IDA for RE插件推荐这篇可能会持续更新起因是某开发巨佬群里说让我出个IDA插件合集，那就直接开搞，正好可以水一篇博客涨涨人气（那不多bb直接进入正题LazyIDA链接：https://github.com/P4nda0s/LazyIDA简化逆向流程这个插件个人已经用成习惯了，属于是没有这个插件就逆不下去了（开个玩笑。功能可以直接看图，这里简单介绍一下我个人最常用几个的功能Convert，直接把ida里面数据转换成python list或者c array，而且可以自己选择数据类型，在提取密文的时候就非常的方便。Fill with NOPs，字面意思，直接把选中的区域全部填充为0x90（不过在其他架构上面这个没用）Paste Data，这个功能非常牛，可以直接在动调的时候把数据粘贴在内存里面，有时候我们解rc4或是异或这种对称加密，直接把密文粘贴到input的内存里面，再断点在解密之后的地方，就可以直接拿到flag。其他的功能可以看Github链接里面的readme，都挺好用的Keypatch链接：https://github.com/keystone-engine/keypatch修改汇编代码，Patch程序。这个插件，用ida的应该没人不装吧不过要注意一下的是，如果改完要运行程序的话，改完记得到 ida 的 Edit->Patch program->Apply patches to input file... 应用你的更改FindCrypt链接：https://github.com/polymorf/findcrypt-yara识别程序里面包含的加密类型这个插件通过识别一些加密函数的特征来识别加密类型，例如base64的表，tea加密的delta等等。当然他有时候可能会不太准，那就只能靠自己识别加密了。重要的还是多做题。Finger链接：https://github.com/aliyunav/Finger阿里巴巴出品的函数识别好像是用的阿里的数据库，通过一些函数特征自动识别函数，然后重命名并且把这个函数标记成绿色。有的时候可以省去很多事情例如强网这个easyre，识别出了fork和remove函数，不然还要临时去搜索一下。可以拖进ida的时候直接点一下 Recognize all functions（大佬能一眼看出来的别骂了D-810链接：https://gitlab.com/eshard/d810匹配公式，直接简化代码计算过程可能概况的不是很对，因为才发现这个插件，大概是直接识别代码里面的计算过程，然后转换成相同的更简单的式子，而且好像还能去掉ollvm，看上去很神奇的插件，还没有实际使用测试，不过具体的可以参考一下这个博客目前在用的确实也就这几个插件了，下次等发现新的插件再更新（（（

【CTF】Reverse LOADER pell方程 nim-lang 蓝帽杯 逆向学习
type: item
date: 2022-07-11T12:46:00+00:00
description: 蓝帽杯初赛逆向LOADER复现分析首先一进来直接开幕雷击可以看到加载了一个程序在里面，点进unk可以发现MZ开头的数据，直接猜想里面有一个程序。当时第一反应是dump程序出来，但是发现dump出来的东西运行不了，于是直接放弃了。后来经过wjh大佬指点，可以直接动调。于是直接开调动调这个也可以讲一点，基本上程序进行输入输出的地方肯定是关键函数。这个题要找到关键函数的话，键盘上先多按f8，注意call哪个函数之后程序输出东西了，那么打个断点，然后重新开始程序再f9到这个地方f7进这个call，这样反复，肯定能快速找到主要函数。例如这边就找到main_0了，然后下面几个call其实点进去看一下就差不多知道了，其实主函数在这里（可以熟练用快捷键n去改一下这些函数名，方便识别。）那么调到这里之后，可以继续往下走，发现下面一个就是输入数据，这个时候可以点进函数返回的数据下去看一下，可以看到这其实是一个结构体，我们可以选择进入structures创建一个结构体。当然也可以不创建。这边这一块，点进数据看一下，可以发现其实是检测前五位是不是flag{同理在这边也可以发现是flag格式的检验，同时可以知道flag总长度是42利用同样的方法，可以很快的知道下面的循环在做的事情，也就是提取flag{}括号内前十八位数据放入v13同理也可以得到下面这个函数的作用，就是把字符串变成int值。（听说可以对照着字符串去nim-lang的源码搜，长知识了）接下来是几个关键的函数，同样可以通过对数据的观察，猜测函数做的事情。例如calculate这个，最开始我是不知道他是干嘛的，因为不像之前的str2int，这个出来之后是一堆奇怪的数字。但是能知道的就是他对v28和v27两个这两个变量（实际存放的是输入flag的前十八位的数字）做了什么操作然后给了v31。那么传入两个数字的话，应该是进行了一系列运算。那么可以先拿出v31的数据，与前十八位的数据进行对比。最后我们可以发现其实这个函数是拿前两个参数相乘，给到第三个参数里面。假如还是说不清楚是干嘛的，可以去源码搜一搜，可以发现是运算的函数，基本上猜一下也就出来了。同理，有好几个乘法，还有一个减法最后这里是一个check，动调可以在上面直接拿到密文9于是我们最后可以得出一个式子$$ inp1^2-11*(inp2^2)=9 $$同时数字需要为18位数也就是100000000000000000<inp1<999999999999999999解答我们把式子直接拿到网站上面可以解出来结果拼接起来发现会少一位，发现y只有17位，那么加个-或者前面加个0应该都行。补充观察到别的师傅的wp里面的x是有一个确切的范围的，应该是前面这一部分判定了x的范围。总结比赛的时候去看取证了，re没做，实际复现起来的话，应该是花了挺久的，可能有三四个小时（还是在看了一点wp，知道是解方程之后才完成的。）不过比赛的时候，可能不会这么顺利，因为会想着把东西dump出来，或者是卡在加减乘除的识别上面。还是做题少了