首页
社区
课程
招聘
[原创]2021 KCTF 春季赛 第六题 寻回宝剑 wp
发表于: 2021-5-18 13:20 7513

[原创]2021 KCTF 春季赛 第六题 寻回宝剑 wp

2021-5-18 13:20
7513

题目是windows64位应用程序.

观察PE文件的Section, 发现有8个节, 最后一个节.cop有可执行权限, 说明应该有加壳或者其他处理.

载入调试器看看EntryPoint代码.

好家伙!往EntryPoint上下翻翻都是清一色的代码块.

简单单步跟踪了一下, 总结混淆方案共有4种.

整个文件大小将近1M了, 可见混淆数量之多.
如果想靠肉眼顶着混淆看代码, 属实不太现实.
看来必须要先写代码对PE文件的混淆做优化, 再来盘程序逻辑了.

针对题目里的4种混淆方案, 需要给出对应的去混淆方法.
不需要优化得很彻底, 只需要能不太费力地使用肉眼看代码逻辑即可.

干到这里留了个心眼.
既然咱们需要patch题目文件优化混淆, 题目会不会有CRC之类的校验代码段, 如果有的话还得先要patch代码校验.
先简单手动修改一处混淆(随便找了个混淆方案1的地方改成jmp指令), 保存文件, 运行.
yes, 运行是没问题, 看来可以放心patch题目文件了.

要patch文件, 首先需要把文件读入到内存中来, Section展开不展开都行.
这里需要注意的是, 题目的ImageBase是默认0x140000000, 申请的地址要满足后面几位也最好都是0, 要不然混淆方案中的xor计算会出错.

混淆方案1等价于jmp指令.
jmp到的地址等于call $+5下一行的地址异或上后面的异或值常量.
这种混淆方案在反汇编代码中随便拉都是, 看来可以先进行一波特征搜索patch掉这些"肉眼可见"的jmp变异.
这里需要注意的是, .text节和.cop节都是代码段, 两个代码段之间会有很多来回的跳转. 没有展开Section的话, 需要注意FA和VA的转换.

混淆方案2等价于jmp指令.
但是混淆方案2的代码在内存中并不是连续的, 不好直接搜索特征来去除.
这里想到个办法, 使用x64dbg的TraceInto/TraceOver功能先跑出代码来, 再针对输出的log文件进行文本分析得到混淆方案2的地址.

x64dbg的TraceInto/TraceOver功能, 要输出到log的内容填上0x{p:cip} {i:cip}, 选择好输出log文件的路径, 设置步数500000(只能多不能少, 至少要跑完输出错误提示吧), 不用设置停止条件, 即可开始trace.

trace出来的文件大概是这样.

一眼望去, 代码里全是"去混淆方案1"中patch的jmp和成对出现的垃圾指令"push reg"/"pop reg".
写个python脚本优化掉(方法见"去混淆方案3").
去掉jmp和push reg/popreg的log文本文件中, 可以见到混淆方案2的代码已经连续出现了.

这里使用notepad++的插件python script写个脚本, 输出针对混淆方案2优化需要用到的几个重要参数(起始地址,callnext返回地址,异或运算常量,加法运算常量).

输出的地址特别多, 整理填入C代码中.

修复混淆方案2的代码(注意FA和RVA的转换):

混淆方案3是垃圾指令, 成对的push reg和pop reg.
写python脚本在log文本中搜索几次, 即可清理干净.
这里内存中就不patch了, 不是很影响看代码.
对python脚本输出的文件可以进行"去混淆方案2"和"去混淆方案4"操作.

混淆方案4等价于call指令.
混淆方案4和混淆方案2的差别, 就是最后一行一个是ret, 一个是jmp.

push addr+ret = jmp addr
push addr1+jmp addr2= call addr2 (addr1是call的返回地址)

在对trace的log进行完"去混淆指令3"和"去混淆指令2"操作后, 混淆方案4的代码就会"浮出水面", 在文本中连续.
继续写python脚本提取输出要处理的信息.

输出的数据填入C代码中, 进行修复.

优化混淆方案4的方法:
1.起始地址jmp到返回地址-5
2.返回地址-5的地址,填入call指令

经过优化代码混淆后, 看一下EntryPoint处代码.

这代码看着就眼熟多了, 一股浓浓的VS201X编译器的味道.

main函数给定位到了:0x0000000140083814
下次trace就可以从main函数开始.

暂时想不到什么很好的办法能把代码全部按顺序修复好让ida能F5, 不过这反汇编代码已经看起来非常舒适了.

又多再看了几眼, 程序编译的时候没有开优化, 反汇编代码看起来又2更亲切了.

多亏笔者在武汉科锐培训三阶段的时候, 练就了看汇编代码还原C代码的"神功", 就当成是培训时间一次正常的作业吧.
^_^

首先是输出字符串到控制台和输入flag.
输入输出使用的std::cout和std::cin.

输入之后首先判断了输入字符串的长度(0x54=84).

接着为一块大小为0x150的局部变量数组初始化数值为0.

观察对改数组的访问得到数组成员size为8字节, 算出总共42个成员, 数组定义如下.

循环往数组内写入数据.
写入数值=取一个字符转数字*0x2A+再取一个字符转数字.

仔细分析字符转数字函数, 得出输入总共有42个字符, 分别是:

0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-*/%=

下标就是这个字符转换出来的数值.

接着循环判断数组QWORD ary[42]中以从小到大顺序排序.

这里说明flag偶数下标的数值是限制死的.
只能是"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-*/%="依次排序.

接着一个check, 循环判断了输入的偶数位和奇数位字符都不一样.

这里可以得到信息,奇数位的中每个字符都只出现一次.

接着下一个check, 嵌套的循环.
大概逻辑是, 相邻的偶数位和奇数位为一组, 对于每两组数据差得到的一个坐标都不能相同(这里形容得不太准确,没有太理解,直接把反汇编代码翻译成C代码写个check函数即可).

这里check逻辑虽然看得不是太懂, 但是突然产生个脑洞.
有点像n皇后问题, 使用回溯法写代码可以解决.
但是看这规模, 跑出flag来估计也要个很长时间, 不太现实.
继续看后面有没有check可以缩小穷举范围.

一看果然有发现:

[rsp+0x1010]是输入的flag
[0x0000000140004521]是"02152S3X4Z5Q6C7T819/ADB%C*DL"

也就是说,flag的前面28个字符已经给定.
范围已经缩到最小, 可以写代码进行穷举了.

百度抄下个n皇后回溯法求解的代码, 修改下check函数和输入输出.

运行出结果需要一段时间, 一两分钟吧, 不算太久.

02152S3X4Z5Q6C7T819/ADB%CDLEIFUG3HRIHJ6K7L0MBNKOJPPQ=RNS+TEUOVWWGXYYMZ9+4-8F/-%V=A

题目主打还是代码流, 很合笔者胃口.
题目算法验证部分最后一个循环check中, 有数组越界访问, 这个很坑, 不按题目算法这样写代码得不到flag.
混淆方法太少, 使得攻击者要恢复代码工作量不算太大.

附件文件:
crack_login.cpp是修复混淆和最后回溯穷举的代码.
KCTF_patch8.exe是优化部分混淆过后的题目可执行文件.
python script.rar是notepad++插件的python脚本.

本人目前待业中, 主要擅长windows的逆向, 研究最多的是代码流的防御和攻击手段, 有公司需要人嘛.
有意的大佬可以在CTF群里联系我, 群备注就是论坛名.

 
 
 
push rax                       
push rax                       
pushfq                         
call $+5           
pop rax                        
xor rax,D1E15                  
mov qword ptr ss:[rsp+10],rax  
popfq                          
pop rax                        
ret
push rax                       
push rax                       
pushfq                         
call $+5           
pop rax                        
xor rax,D1E15                  
mov qword ptr ss:[rsp+10],rax  
popfq                          
pop rax                        
ret
push rax
push rax
pushfq
push rax
push rax
pushfq
call $+5  
pop rax
xor rax, 0xE4EB3
mov qword ptr ss:[rsp+0x10], rax
popfq
pop rax
pop rax
add rax, 0x8242E
mov qword ptr ss:[rsp+0x10], rax
popfq
pop rax
ret
push rax
push rax
pushfq
push rax
push rax
pushfq
call $+5  
pop rax
xor rax, 0xE4EB3
mov qword ptr ss:[rsp+0x10], rax
popfq
pop rax
pop rax
add rax, 0x8242E
mov qword ptr ss:[rsp+0x10], rax
popfq
pop rax
ret
push rdx
push rdx
pop rdx
pop rdx
push rcx
push rdx
pop rdx
push rbx
pop rbx
pop rcx
push rdx
push rdx
pop rdx
pop rdx
push rcx
push rdx
pop rdx
push rbx
pop rbx
pop rcx
push rax
push rax
pushfq
push rax
push rax
pushfq
call $+5 
pop rax
xor rax, 0xDC85F
mov qword ptr ss:[rsp+0x10], rax
popfq
pop rax
pop rax
add rax, 0x51438
mov qword ptr ss:[rsp+0x10], rax
popfq
pop rax
jmp 0x00000001400979D6
push rax
push rax
pushfq
push rax
push rax
pushfq
call $+5 
pop rax
xor rax, 0xDC85F
mov qword ptr ss:[rsp+0x10], rax
popfq
pop rax
pop rax
add rax, 0x51438
mov qword ptr ss:[rsp+0x10], rax
popfq
pop rax
jmp 0x00000001400979D6
 
 
static uintptr_t g_nFileSize = 0;
static LPBYTE g_lpFileBuffer = 0;
 
void ReadPEFile()
{
    HANDLE hFile = NULL;
    HANDLE hMapFile = NULL;
    LPBYTE lpFileBuffer = NULL;
 
    hFile = CreateFileA("D:\\Projects\\KCTF2021Spring\\CrackNote\\6\\KCTF.exe",           // open MYFILE.TXT
        GENERIC_READ,              // open for reading
        FILE_SHARE_READ,           // share for reading
        NULL,                      // no security
        OPEN_EXISTING,             // existing file only
        FILE_ATTRIBUTE_NORMAL,     // normal file
        NULL);
    if (hFile == INVALID_HANDLE_VALUE)
    {
        std::cout << "Could not create file." << std::endl;
        goto EXIT_PROC;
    }
 
    g_nFileSize = GetFileSize(hFile, NULL);
    if (g_nFileSize == INVALID_FILE_SIZE)
    {
        std::cout << "GetFileSize error." << std::endl;
        goto EXIT_PROC;
    }
 
 
    hMapFile = CreateFileMappingA(hFile, NULL, PAGE_READONLY,
        0, 0, NULL);
    if (hMapFile == NULL)
    {
        std::cout << "Could not create file-mapping object." << std::endl;
        goto EXIT_PROC;
    }
 
 
    lpFileBuffer = (LPBYTE)MapViewOfFile(hMapFile,  // Handle to mapping object.
        FILE_MAP_READ,                        // Read/write permission
        0,                                    // Max. object size.
        0,                                    // Size of hFile.
        0);                                   // Map entire file.
    if (lpFileBuffer == NULL)
    {
        std::cout << "MapViewOfFile error." << std::endl;
        goto EXIT_PROC;
    }
 
   g_lpFileBuffer = new BYTE[g_nFileSize + 0x100000000];
   g_lpFileBuffer = (LPBYTE)(((QWORD)g_lpFileBuffer & 0xFFFFFFFF00000000) + 0x100000000);
    if (g_lpFileBuffer == NULL)
    {
        std::cout << "Alloc error." << std::endl;
        goto EXIT_PROC;
    }
    memcpy(g_lpFileBuffer, lpFileBuffer, g_nFileSize);
 
 
EXIT_PROC:
    if (lpFileBuffer != NULL)
    {
        UnmapViewOfFile(lpFileBuffer);
        lpFileBuffer = NULL;
    }
 
    if (hMapFile != NULL)
    {
        CloseHandle(hMapFile);
        hMapFile = NULL;
    }
 
    if (hFile != INVALID_HANDLE_VALUE)
    {
        CloseHandle(hFile);
        hFile = INVALID_HANDLE_VALUE;
    }
}
static uintptr_t g_nFileSize = 0;
static LPBYTE g_lpFileBuffer = 0;
 
void ReadPEFile()
{
    HANDLE hFile = NULL;
    HANDLE hMapFile = NULL;
    LPBYTE lpFileBuffer = NULL;
 
    hFile = CreateFileA("D:\\Projects\\KCTF2021Spring\\CrackNote\\6\\KCTF.exe",           // open MYFILE.TXT
        GENERIC_READ,              // open for reading
        FILE_SHARE_READ,           // share for reading
        NULL,                      // no security
        OPEN_EXISTING,             // existing file only
        FILE_ATTRIBUTE_NORMAL,     // normal file
        NULL);
    if (hFile == INVALID_HANDLE_VALUE)
    {
        std::cout << "Could not create file." << std::endl;
        goto EXIT_PROC;
    }
 
    g_nFileSize = GetFileSize(hFile, NULL);
    if (g_nFileSize == INVALID_FILE_SIZE)
    {
        std::cout << "GetFileSize error." << std::endl;
        goto EXIT_PROC;
    }
 
 
    hMapFile = CreateFileMappingA(hFile, NULL, PAGE_READONLY,
        0, 0, NULL);
    if (hMapFile == NULL)
    {
        std::cout << "Could not create file-mapping object." << std::endl;
        goto EXIT_PROC;
    }
 
 
    lpFileBuffer = (LPBYTE)MapViewOfFile(hMapFile,  // Handle to mapping object.
        FILE_MAP_READ,                        // Read/write permission
        0,                                    // Max. object size.
        0,                                    // Size of hFile.
        0);                                   // Map entire file.
    if (lpFileBuffer == NULL)
    {
        std::cout << "MapViewOfFile error." << std::endl;
        goto EXIT_PROC;
    }
 
   g_lpFileBuffer = new BYTE[g_nFileSize + 0x100000000];
   g_lpFileBuffer = (LPBYTE)(((QWORD)g_lpFileBuffer & 0xFFFFFFFF00000000) + 0x100000000);
    if (g_lpFileBuffer == NULL)
    {
        std::cout << "Alloc error." << std::endl;
        goto EXIT_PROC;
    }
    memcpy(g_lpFileBuffer, lpFileBuffer, g_nFileSize);
 
 
EXIT_PROC:
    if (lpFileBuffer != NULL)
    {
        UnmapViewOfFile(lpFileBuffer);
        lpFileBuffer = NULL;
    }
 
    if (hMapFile != NULL)
    {
        CloseHandle(hMapFile);
        hMapFile = NULL;
    }
 
    if (hFile != INVALID_HANDLE_VALUE)
    {
        CloseHandle(hFile);
        hFile = INVALID_HANDLE_VALUE;
    }
}
void AntiObfuscation1()
{
    LPBYTE lpStart = 0;
    LPBYTE lpEnd = 0;
    DWORD dwCount = 0;
 
    //.text节
    lpStart = g_lpFileBuffer+0x400;
    lpEnd = lpStart + 0x3000;
    dwCount = 0;
    while (true)
    {
        //50509CE800000000584835????????48894424109D58C3
        LPBYTE lpResult = (LPBYTE)FindHexBytes(lpStart, lpEnd, "50509CE800000000584835????????48894424109D58C3");
        if (lpResult == (LPVOID)-1) {
 
            break;
        }
        else {
            dwCount++;
            lpStart = lpResult + 1;
 
            QWORD dwFindFA = (QWORD)lpResult;
            QWORD dwFindVA = dwFindFA - 0x400 + 0x1000;
 
            QWORD dwCallNextFA = (QWORD)lpResult + 8;
            QWORD dwCallNextVA = dwCallNextFA -  0x400 + 0x1000 ;// 修复内存地址
 
            QWORD dwXor = Mem_RDword(lpResult + 11);
 
            QWORD dwNextAddrVA = dwXor ^ dwCallNextVA;
            QWORD dwNextAddrFA = 0;
 
            BYTE aryNop[25] = {
                0x90, 0x90, 0x90, 0x90, 0x90,
                0x90, 0x90, 0x90, 0x90, 0x90,
                0x90, 0x90, 0x90, 0x90, 0x90,
                0x90, 0x90, 0x90, 0x90, 0x90,
                0x90, 0x90, 0x90, 0x90, 0x90,
            };
 
            //混淆方案1的opcode size 固定是23
            Mem_WBytes2((LPVOID)dwFindFA, aryNop, 23);
 
            BYTE bHook[] = { 0xE9, 00, 00, 00, 00 };
            Mem_WDword(bHook + 1, (DWORD)(dwNextAddrVA - dwFindVA - 5));
            Mem_WBytes2((LPVOID)dwFindFA, bHook, 5);
        }
    }
    D("patch .text %d addr", dwCount);
 
 
    //.cop节
    lpStart = g_lpFileBuffer + 0x6200;
    lpEnd = lpStart + 0xF0000;
    dwCount = 0;
    while (true)
    {
        //50509CE800000000584835????????48894424109D58C3
        LPBYTE lpResult = (LPBYTE)FindHexBytes(lpStart, lpEnd, "50509CE800000000584835????????48894424109D58C3");
        if (lpResult == (LPVOID)-1) {
 
            break;
        }
        else {
            dwCount++;
            lpStart = lpResult + 1;
 
            QWORD dwFindFA = (QWORD)lpResult;
            QWORD dwFindVA = dwFindFA - 0x6200 + 0xB000;
 
            QWORD dwCallNextFA = (QWORD)lpResult + 8;
            QWORD dwCallNextVA = dwCallNextFA - 0x6200 + 0xB000;// 修复内存地址
 
            QWORD dwXor = Mem_RDword(lpResult + 11);
 
            QWORD dwNextAddrVA = dwXor ^ dwCallNextVA;
            QWORD dwNextAddrFA = 0;
 
            BYTE aryNop[25] = {
                0x90, 0x90, 0x90, 0x90, 0x90,
                0x90, 0x90, 0x90, 0x90, 0x90,
                0x90, 0x90, 0x90, 0x90, 0x90,
                0x90, 0x90, 0x90, 0x90, 0x90,
                0x90, 0x90, 0x90, 0x90, 0x90,
            };
 
            //混淆方案1的opcode size 固定是23
            Mem_WBytes2((LPVOID)dwFindFA, aryNop, 23);
 
            BYTE bHook[] = { 0xE9, 00, 00, 00, 00 };
            Mem_WDword(bHook + 1, (DWORD)(dwNextAddrVA - dwFindVA - 5));
            Mem_WBytes2((LPVOID)dwFindFA, bHook, 5);
        }
    }
    D("patch .cop  %d addr", dwCount);
}
void AntiObfuscation1()
{
    LPBYTE lpStart = 0;
    LPBYTE lpEnd = 0;
    DWORD dwCount = 0;
 
    //.text节
    lpStart = g_lpFileBuffer+0x400;
    lpEnd = lpStart + 0x3000;
    dwCount = 0;
    while (true)
    {
        //50509CE800000000584835????????48894424109D58C3
        LPBYTE lpResult = (LPBYTE)FindHexBytes(lpStart, lpEnd, "50509CE800000000584835????????48894424109D58C3");
        if (lpResult == (LPVOID)-1) {
 
            break;
        }
        else {
            dwCount++;
            lpStart = lpResult + 1;
 
            QWORD dwFindFA = (QWORD)lpResult;
            QWORD dwFindVA = dwFindFA - 0x400 + 0x1000;
 
            QWORD dwCallNextFA = (QWORD)lpResult + 8;
            QWORD dwCallNextVA = dwCallNextFA -  0x400 + 0x1000 ;// 修复内存地址
 
            QWORD dwXor = Mem_RDword(lpResult + 11);
 
            QWORD dwNextAddrVA = dwXor ^ dwCallNextVA;
            QWORD dwNextAddrFA = 0;
 
            BYTE aryNop[25] = {
                0x90, 0x90, 0x90, 0x90, 0x90,
                0x90, 0x90, 0x90, 0x90, 0x90,
                0x90, 0x90, 0x90, 0x90, 0x90,
                0x90, 0x90, 0x90, 0x90, 0x90,
                0x90, 0x90, 0x90, 0x90, 0x90,
            };
 
            //混淆方案1的opcode size 固定是23
            Mem_WBytes2((LPVOID)dwFindFA, aryNop, 23);
 
            BYTE bHook[] = { 0xE9, 00, 00, 00, 00 };
            Mem_WDword(bHook + 1, (DWORD)(dwNextAddrVA - dwFindVA - 5));
            Mem_WBytes2((LPVOID)dwFindFA, bHook, 5);
        }
    }
    D("patch .text %d addr", dwCount);
 
 
    //.cop节
    lpStart = g_lpFileBuffer + 0x6200;
    lpEnd = lpStart + 0xF0000;
    dwCount = 0;
    while (true)
    {
        //50509CE800000000584835????????48894424109D58C3
        LPBYTE lpResult = (LPBYTE)FindHexBytes(lpStart, lpEnd, "50509CE800000000584835????????48894424109D58C3");
        if (lpResult == (LPVOID)-1) {
 
            break;
        }
        else {
            dwCount++;
            lpStart = lpResult + 1;
 
            QWORD dwFindFA = (QWORD)lpResult;
            QWORD dwFindVA = dwFindFA - 0x6200 + 0xB000;
 
            QWORD dwCallNextFA = (QWORD)lpResult + 8;
            QWORD dwCallNextVA = dwCallNextFA - 0x6200 + 0xB000;// 修复内存地址
 
            QWORD dwXor = Mem_RDword(lpResult + 11);
 
            QWORD dwNextAddrVA = dwXor ^ dwCallNextVA;
            QWORD dwNextAddrFA = 0;
 
            BYTE aryNop[25] = {
                0x90, 0x90, 0x90, 0x90, 0x90,
                0x90, 0x90, 0x90, 0x90, 0x90,
                0x90, 0x90, 0x90, 0x90, 0x90,
                0x90, 0x90, 0x90, 0x90, 0x90,
                0x90, 0x90, 0x90, 0x90, 0x90,
            };
 
            //混淆方案1的opcode size 固定是23
            Mem_WBytes2((LPVOID)dwFindFA, aryNop, 23);
 
            BYTE bHook[] = { 0xE9, 00, 00, 00, 00 };
            Mem_WDword(bHook + 1, (DWORD)(dwNextAddrVA - dwFindVA - 5));
            Mem_WBytes2((LPVOID)dwFindFA, bHook, 5);
        }
    }
    D("patch .cop  %d addr", dwCount);
}
 
 
 
 
a = editor.getText()
lst=a.split("\n")
 
lstdel=[]
 
for index in range(len(lst)-18):
#for index in range(20):
    i1=lst[index][-8:]
    i2=lst[index+1][-8:]
    i3=lst[index+2][-6:]
    i17=lst[index+17][-3:]
    #print(i1,i2,i3,i17)
    if(i1=="push rax" and i2=="push rax" and i3=="pushfq" and i17=="ret"):
        eva=lst[index][:18]
        cnva=lst[index+7][:18]
        xi=lst[index+8].rfind(" ");
        x=lst[index+8][xi:]
        ai=lst[index+13].rfind(" ");
        a=lst[index+13][ai:]
        print(eva, cnva, x, a)
 
print("finish.")
a = editor.getText()
lst=a.split("\n")
 
lstdel=[]
 
for index in range(len(lst)-18):
#for index in range(20):
    i1=lst[index][-8:]
    i2=lst[index+1][-8:]
    i3=lst[index+2][-6:]
    i17=lst[index+17][-3:]
    #print(i1,i2,i3,i17)
    if(i1=="push rax" and i2=="push rax" and i3=="pushfq" and i17=="ret"):
        eva=lst[index][:18]
        cnva=lst[index+7][:18]
        xi=lst[index+8].rfind(" ");
        x=lst[index+8][xi:]
        ai=lst[index+13].rfind(" ");
        a=lst[index+13][ai:]
        print(eva, cnva, x, a)
 
print("finish.")
LPCSTR g_aryFix[] = {
"0x00000001400B5E68", "0x000000014007FBD8", "0x6665", "0x36F74",
"0x000000014005AF49", "0x000000014002BB97", "0x28376", "0xCFCD7",
"0x00000001400E05AD", "0x0000000140040B81", "0xD7FA9", "0xFFFFFFFFFFFE178B",
"0x000000014000151A", "0x000000014008F26F", "0xDB257", "0x78C45",
"0x0000000140029C72", "0x000000014008F92C", "0xEB504", "0x328B9",
"0x000000014001E0A6", "0x00000001400F1BA1", "0x6545B", "0x28976",
"0x0000000140052153", "0x0000000140012134", "0x485D5", "0xFFFFFFFFFFFF07DE",
"0x0000000140083D5A", "0x000000014000F6CA", "0x43749", "0x46ACE",
"0x000000014002C47E", "0x00000001400C2EFA", "0xA5AD1", "0x89CB0",
"0x00000001400E7AEC", "0x00000001400370EC", "0xFEA16", "0xFFFFFFFFFFFD4BAC",
"0x00000001400C0C09", "0x00000001400F44A9", "0x2F746", "0xFFFFFFFFFFF323E7",
"0x000000014001533A", "0x0000000140020B70", "0x15CD7", "0x5E0A2",
"0x00000001400572A6", "0x0000000140059016", "0xFBD1", "0xFFFFFFFFFFFDF0F0",
"0x0000000140022F8A", "0x00000001400767A4", "0x4BE4C", "0x88F4",
//... ...
};
LPCSTR g_aryFix[] = {
"0x00000001400B5E68", "0x000000014007FBD8", "0x6665", "0x36F74",
"0x000000014005AF49", "0x000000014002BB97", "0x28376", "0xCFCD7",
"0x00000001400E05AD", "0x0000000140040B81", "0xD7FA9", "0xFFFFFFFFFFFE178B",
"0x000000014000151A", "0x000000014008F26F", "0xDB257", "0x78C45",
"0x0000000140029C72", "0x000000014008F92C", "0xEB504", "0x328B9",
"0x000000014001E0A6", "0x00000001400F1BA1", "0x6545B", "0x28976",
"0x0000000140052153", "0x0000000140012134", "0x485D5", "0xFFFFFFFFFFFF07DE",
"0x0000000140083D5A", "0x000000014000F6CA", "0x43749", "0x46ACE",
"0x000000014002C47E", "0x00000001400C2EFA", "0xA5AD1", "0x89CB0",
"0x00000001400E7AEC", "0x00000001400370EC", "0xFEA16", "0xFFFFFFFFFFFD4BAC",
"0x00000001400C0C09", "0x00000001400F44A9", "0x2F746", "0xFFFFFFFFFFF323E7",
"0x000000014001533A", "0x0000000140020B70", "0x15CD7", "0x5E0A2",
"0x00000001400572A6", "0x0000000140059016", "0xFBD1", "0xFFFFFFFFFFFDF0F0",
"0x0000000140022F8A", "0x00000001400767A4", "0x4BE4C", "0x88F4",
//... ...
};
void AntiObfuscation2()
{
    for (int i = 0; i < sizeof(g_aryFix) / sizeof(g_aryFix[0]) / 4 ;i++)
    {
        QWORD dwFindRVA = strtoull(g_aryFix[i * 4 ], 0, 16) - 0x140000000;
        QWORD dwFindFA = 0;
        if (dwFindRVA <  0x3400)
        {
            dwFindFA = (QWORD)g_lpFileBuffer + dwFindRVA - 0x1000 + 0x400;
        }
        else
        {
            dwFindFA = (QWORD)g_lpFileBuffer + dwFindRVA - 0xB000 + 0x6200;
        }
 
        QWORD dwCallNextRVA= strtoull(g_aryFix[i * 4+1], 0, 16) - 0x140000000;
 
        QWORD dwXor = strtoull(g_aryFix[i * 4 + 2], 0, 16);
        QWORD dwAdd = strtoull(g_aryFix[i * 4 + 3], 0, 16);
 
        QWORD dwNextAddrRVA = (dwXor ^ dwCallNextRVA) + dwAdd;
 
        BYTE bHook[] = { 0xE9, 00, 00, 00, 00 };
        Mem_WDword(bHook + 1, (DWORD)(dwNextAddrRVA - dwFindRVA - 5));
        Mem_WBytes2((LPVOID)dwFindFA, bHook, 5);
    }
}
void AntiObfuscation2()
{
    for (int i = 0; i < sizeof(g_aryFix) / sizeof(g_aryFix[0]) / 4 ;i++)
    {
        QWORD dwFindRVA = strtoull(g_aryFix[i * 4 ], 0, 16) - 0x140000000;
        QWORD dwFindFA = 0;
        if (dwFindRVA <  0x3400)
        {
            dwFindFA = (QWORD)g_lpFileBuffer + dwFindRVA - 0x1000 + 0x400;
        }
        else
        {
            dwFindFA = (QWORD)g_lpFileBuffer + dwFindRVA - 0xB000 + 0x6200;
        }
 
        QWORD dwCallNextRVA= strtoull(g_aryFix[i * 4+1], 0, 16) - 0x140000000;
 
        QWORD dwXor = strtoull(g_aryFix[i * 4 + 2], 0, 16);
        QWORD dwAdd = strtoull(g_aryFix[i * 4 + 3], 0, 16);
 
        QWORD dwNextAddrRVA = (dwXor ^ dwCallNextRVA) + dwAdd;
 
        BYTE bHook[] = { 0xE9, 00, 00, 00, 00 };
        Mem_WDword(bHook + 1, (DWORD)(dwNextAddrRVA - dwFindRVA - 5));
        Mem_WBytes2((LPVOID)dwFindFA, bHook, 5);
    }
}
a = editor.getText()
 
lst=a.split("\n")
print(len(lst));
 
lstdel=[]
 
for index in range(len(lst)):
    if(lst[index][-22:-19] == "jmp"):
        lstdel.append(index)
 
lstdel.reverse()
print(len(lstdel))
for index in range(len(lstdel)):
    del lst[lstdel[index]]
 
for fxcktime in range(10):
    lstdel=[]
    for index in range(len(lst)-1):
        i1=lst[index][-8:-4]
        i2=lst[index+1][-7:-4]
        reg1=lst[index][-3:]
        reg2=lst[index+1][-3:]
        if(i1=="push" and i2=="pop" and reg1==reg2):
            #print(i1,reg1,i2,reg2)
            lstdel.append(index)
            lstdel.append(index+1)
    lstdel.reverse()
    for index in range(len(lstdel)):
        del lst[lstdel[index]]
 
fo=open("D:\\Projects\\KCTF2021Spring\\CrackNote\\6\\crack\\crack\\pyoutput.txt","w")
for index in range(len(lst)):
    fo.write(lst[index]+"\n")
fo.close()
 
 
print("finish.");
a = editor.getText()
 
lst=a.split("\n")
print(len(lst));
 
lstdel=[]
 
for index in range(len(lst)):
    if(lst[index][-22:-19] == "jmp"):
        lstdel.append(index)
 
lstdel.reverse()
print(len(lstdel))
for index in range(len(lstdel)):
    del lst[lstdel[index]]
 
for fxcktime in range(10):
    lstdel=[]
    for index in range(len(lst)-1):
        i1=lst[index][-8:-4]
        i2=lst[index+1][-7:-4]
        reg1=lst[index][-3:]
        reg2=lst[index+1][-3:]
        if(i1=="push" and i2=="pop" and reg1==reg2):
            #print(i1,reg1,i2,reg2)
            lstdel.append(index)
            lstdel.append(index+1)
    lstdel.reverse()
    for index in range(len(lstdel)):
        del lst[lstdel[index]]
 
fo=open("D:\\Projects\\KCTF2021Spring\\CrackNote\\6\\crack\\crack\\pyoutput.txt","w")
for index in range(len(lst)):
    fo.write(lst[index]+"\n")
fo.close()
 
 
print("finish.");
 
a = editor.getText()
lst=a.split("\n")
 
lstdel=[]
 
for index in range(len(lst)-18):
    i1=lst[index][-8:]
    i2=lst[index+1][-8:]
    i3=lst[index+2][-6:]
    i17=lst[index+16][-7:]
    #print(i1,i2,i3,i17)
    if(i1=="push rax" and i2=="push rax" and i3=="pushfq" and i17=="pop rax"):
        eva=lst[index][:18]
        cnva=lst[index+7][:18]
        callva=lst[index+17][:18]
        xi=lst[index+8].rfind(" ");
        x=lst[index+8][xi:]
        ai=lst[index+13].rfind(" ");
        a=lst[index+13][ai:]
        print(eva, cnva, x, a, callva)
 
print("finish.")
a = editor.getText()
lst=a.split("\n")
 
lstdel=[]
 
for index in range(len(lst)-18):
    i1=lst[index][-8:]
    i2=lst[index+1][-8:]
    i3=lst[index+2][-6:]
    i17=lst[index+16][-7:]
    #print(i1,i2,i3,i17)
    if(i1=="push rax" and i2=="push rax" and i3=="pushfq" and i17=="pop rax"):
        eva=lst[index][:18]
        cnva=lst[index+7][:18]
        callva=lst[index+17][:18]
        xi=lst[index+8].rfind(" ");
        x=lst[index+8][xi:]
        ai=lst[index+13].rfind(" ");
        a=lst[index+13][ai:]
        print(eva, cnva, x, a, callva)
 
print("finish.")
LPCSTR g_aryFixC[] = {
"0x000000014007A4C4", "0x0000000140089E51", "0xDC85F", "0x51438", "0x00000001400979D8",
"0x00000001400ADE90", "0x00000001400D4AEB", "0x4E2ED", "0xFFFFFFFFFFFD199D", "0x0000000140060882",
"0x00000001400C4678", "0x0000000140020DE5", "0xD2FE3", "0xFFFFFFFFFFFBE04E", "0x000000014005CC6E",
"0x00000001400C673D", "0x00000001400E7B10", "0xEB97C", "0x6DDA4", "0x000000014003F7D0",
"0x000000014003AF3E", "0x00000001400DDF75", "0x9704D", "0xFFFFFFFFFFFF5B08", "0x000000014003F7D0",
"0x00000001400839E3", "0x000000014007BECA", "0x36372", "0xA777F", "0x00000001400F90F3",
"0x00000001400543F0", "0x00000001400A164B", "0xAF7C5", "0x5CDEC", "0x0000000140078E09",
"0x00000001400998CB", "0x00000001400B928A", "0x2C92F", "0xE4AC", "0x00000001400D031B",
"0x000000014007C0AC", "0x000000014009B414", "0xC2AD8", "0xFFFFFFFFFFFC7598", "0x00000001400D42F1",
"0x000000014008FBE2", "0x0000000140047E12", "0x56408", "0x65F02", "0x00000001400728A0",
"0x000000014006B5D5", "0x00000001400194CA", "0x78E10", "0x3996", "0x0000000140078E09",
"0x0000000140077920", "0x00000001400A2374", "0x4FE21", "0xFFFFFFFFFFFCEA1A", "0x0000000140039068",
"0x00000001400943F5", "0x000000014008595F", "0xF3ADF", "0xFFFFFFFFFFFA3AAE", "0x00000001400DFCB3",
"0x000000014003768E", "0x000000014005087F", "0x45B11", "0xAB445", "0x000000014002650B",
//... ...
};
LPCSTR g_aryFixC[] = {
"0x000000014007A4C4", "0x0000000140089E51", "0xDC85F", "0x51438", "0x00000001400979D8",
"0x00000001400ADE90", "0x00000001400D4AEB", "0x4E2ED", "0xFFFFFFFFFFFD199D", "0x0000000140060882",
"0x00000001400C4678", "0x0000000140020DE5", "0xD2FE3", "0xFFFFFFFFFFFBE04E", "0x000000014005CC6E",
"0x00000001400C673D", "0x00000001400E7B10", "0xEB97C", "0x6DDA4", "0x000000014003F7D0",
"0x000000014003AF3E", "0x00000001400DDF75", "0x9704D", "0xFFFFFFFFFFFF5B08", "0x000000014003F7D0",
"0x00000001400839E3", "0x000000014007BECA", "0x36372", "0xA777F", "0x00000001400F90F3",
"0x00000001400543F0", "0x00000001400A164B", "0xAF7C5", "0x5CDEC", "0x0000000140078E09",
"0x00000001400998CB", "0x00000001400B928A", "0x2C92F", "0xE4AC", "0x00000001400D031B",
"0x000000014007C0AC", "0x000000014009B414", "0xC2AD8", "0xFFFFFFFFFFFC7598", "0x00000001400D42F1",
"0x000000014008FBE2", "0x0000000140047E12", "0x56408", "0x65F02", "0x00000001400728A0",
"0x000000014006B5D5", "0x00000001400194CA", "0x78E10", "0x3996", "0x0000000140078E09",
"0x0000000140077920", "0x00000001400A2374", "0x4FE21", "0xFFFFFFFFFFFCEA1A", "0x0000000140039068",
"0x00000001400943F5", "0x000000014008595F", "0xF3ADF", "0xFFFFFFFFFFFA3AAE", "0x00000001400DFCB3",
"0x000000014003768E", "0x000000014005087F", "0x45B11", "0xAB445", "0x000000014002650B",
//... ...
};
void AntiObfuscation3()
{
    for (int i = 0; i < sizeof(g_aryFixC) / sizeof(g_aryFixC[0]) / 5; i++)
    {
        QWORD dwFindRVA = strtoull(g_aryFixC[i * 5], 0, 16) - 0x140000000;
        QWORD dwFindFA = 0;
        if (dwFindRVA < 0x3400)
        {
            dwFindFA = (QWORD)g_lpFileBuffer + dwFindRVA - 0x1000 + 0x400;
        }
        else
        {
            dwFindFA = (QWORD)g_lpFileBuffer + dwFindRVA - 0xB000 + 0x6200;
        }
 
        QWORD dwCallNextRVA = strtoull(g_aryFixC[i * 5 + 1], 0, 16) - 0x140000000;
 
        QWORD dwXor = strtoull(g_aryFixC[i * 5 + 2], 0, 16);
        QWORD dwAdd = strtoull(g_aryFixC[i * 5 + 3], 0, 16);
 
        QWORD dwReturnRVA = (dwXor ^ dwCallNextRVA) + dwAdd;
 
        QWORD dwCallRVA= strtoull(g_aryFixC[i * 5+4], 0, 16) - 0x140000000;
 
        QWORD dwHookRVA = dwReturnRVA - 5 ;
        QWORD dwHookFA = 0;
        if (dwHookRVA < 0x3400)
        {
            dwHookFA = (QWORD)g_lpFileBuffer + dwHookRVA - 0x1000 + 0x400;
        }
        else
        {
            dwHookFA = (QWORD)g_lpFileBuffer + dwHookRVA - 0xB000 + 0x6200;
        }
 
        //BYTE nop[] = { 0x90,0x90,0x90,0x90,0x90 };
        //if (memcmp((LPBYTE)dwHookFA, nop, 5) != 0)
        //{
        //    printf("5 nops is not found.\r\n");
        //}
 
 
        BYTE bHook[] = { 0xE9, 00, 00, 00, 00 };
        Mem_WDword(bHook + 1, (DWORD)(dwHookRVA - dwFindRVA - 5));
        Mem_WBytes2((LPVOID)dwFindFA, bHook, 5);
 
 
        BYTE bHook2[] = { 0xE8, 00, 00, 00, 00 };
        Mem_WDword(bHook2 + 1, (DWORD)(dwCallRVA - dwHookRVA - 5));
        Mem_WBytes2((LPVOID)dwHookFA, bHook2, 5);
 
    }
}
void AntiObfuscation3()
{
    for (int i = 0; i < sizeof(g_aryFixC) / sizeof(g_aryFixC[0]) / 5; i++)
    {
        QWORD dwFindRVA = strtoull(g_aryFixC[i * 5], 0, 16) - 0x140000000;
        QWORD dwFindFA = 0;
        if (dwFindRVA < 0x3400)
        {
            dwFindFA = (QWORD)g_lpFileBuffer + dwFindRVA - 0x1000 + 0x400;
        }
        else
        {
            dwFindFA = (QWORD)g_lpFileBuffer + dwFindRVA - 0xB000 + 0x6200;
        }
 
        QWORD dwCallNextRVA = strtoull(g_aryFixC[i * 5 + 1], 0, 16) - 0x140000000;
 
        QWORD dwXor = strtoull(g_aryFixC[i * 5 + 2], 0, 16);
        QWORD dwAdd = strtoull(g_aryFixC[i * 5 + 3], 0, 16);
 
        QWORD dwReturnRVA = (dwXor ^ dwCallNextRVA) + dwAdd;
 
        QWORD dwCallRVA= strtoull(g_aryFixC[i * 5+4], 0, 16) - 0x140000000;
 
        QWORD dwHookRVA = dwReturnRVA - 5 ;
        QWORD dwHookFA = 0;
        if (dwHookRVA < 0x3400)
        {
            dwHookFA = (QWORD)g_lpFileBuffer + dwHookRVA - 0x1000 + 0x400;
        }
        else
        {

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2021-5-19 16:16 被KuCha128编辑 ,原因:
上传的附件:
收藏
免费 5
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//