吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1051|回复: 32
收起左侧

[求助] x64dbg输出日志太长容不下咋办?

  [复制链接]
冥界3大法王 发表于 2023-3-30 11:35
譬如:
bplog 00007FF6DC82F4A8 ,地址00007FF6DC82F4A8 RAX寄存器字符串:{s:RAX}RBX寄存器字符串:{s:RBX} RCX寄存器字符串:{s:RCX}RDX寄存器字符串:{s:RDX}RBP寄存器字符串:{s:RBP}RSP寄存器字符串:{s:RSP}RSI寄存器字符串:{s:RSI}RDI寄q存器字符串:{s:RDI}R8寄存器字符串:{s:R8}R9寄存器字符串:{s:R9}R10寄存器字符串:{s:R10}R11寄存器字符串:{s:r11}R12寄存器字符串:{s:R12}R13寄存器字符串:{s:R13}R14寄存器字符串:{s:R14}R15寄存器字符串:{s:R15}
image.png
输出结果和预想的不一样啊。

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
cjcmxc + 1 + 1 我很赞同!

查看全部评分

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

 楼主| 冥界3大法王 发表于 2023-3-31 09:48
@evea

[C++] 纯文本查看 复制代码
#include "formatfunctions.h"
#include "threading.h"
#include "value.h"
#include "memory.h"
#include "exception.h"
#include "ntdll/ntdll.h"
#include "disasm_fast.h"

std::unordered_map<String, FormatFunctions::Function> FormatFunctions::mFunctions;

static FORMATRESULT formatErrorMsg(HMODULE DLL, const String & errName, DWORD code, char* dest, size_t destCount)
{
    const NTSTATUS ErrorStatus = code;
    PMESSAGE_RESOURCE_ENTRY Entry;
    NTSTATUS Status = RtlFindMessage(DLL,
                                     LDR_FORMAT_MESSAGE_FROM_SYSTEM_MESSAGE_TABLE,
                                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                                     ErrorStatus,
                                     &Entry);
    if(!NT_SUCCESS(Status))
    {
        if(destCount < errName.size() + 1)
            return FORMAT_BUFFER_TOO_SMALL;
        else
        {
            memcpy(dest, errName.c_str(), errName.size() + 1);
            return FORMAT_SUCCESS;
        }
    }

    if((Entry->Flags & MESSAGE_RESOURCE_UNICODE) != 0)
    {
        String UTF8Description = StringUtils::TrimRight(StringUtils::Utf16ToUtf8((const wchar_t*)Entry->Text));
        if(UTF8Description.size() + 3 + errName.size() > destCount)
            return FORMAT_BUFFER_TOO_SMALL;
        else
        {
            sprintf_s(dest, destCount, "%s: %s", errName.c_str(), UTF8Description.c_str());
            return FORMAT_SUCCESS;
        }
    }
    else
    {
        String UTF8Description = StringUtils::TrimRight(StringUtils::LocalCpToUtf8((const char*)Entry->Text));
        if(UTF8Description.size() + 3 + errName.size() > destCount)
            return FORMAT_BUFFER_TOO_SMALL;
        else
        {
            sprintf_s(dest, destCount, "%s: %s", errName.c_str(), UTF8Description.c_str());
            return FORMAT_SUCCESS;
        }
    }
}

template<class Char, size_t DefaultSize = 0>
static FORMATRESULT memoryFormatter(char* dest, size_t destCount, int argc, char* argv[], duint addr, const std::function<String(std::vector<Char>&)> & format)
{
    duint size = DefaultSize;
    if(argc > 1 && !valfromstring(argv[1], &size))
    {
        strcpy_s(dest, destCount, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Invalid argument...")));
        return FORMAT_ERROR_MESSAGE;
    }
    if(size == 0)
    {
        strcpy_s(dest, destCount, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Not enough arguments...")));
        return FORMAT_ERROR_MESSAGE;
    }
    if(size > 1024 * 1024 * 10) //10MB max
    {
        strcpy_s(dest, destCount, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Too much data (10MB max)...")));
        return FORMAT_ERROR_MESSAGE;
    }
    std::vector<Char> data(size);
    if(!MemRead(addr, data.data(), size * sizeof(Char)))
    {
        strcpy_s(dest, destCount, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Failed to read memory...")));
        return FORMAT_ERROR_MESSAGE;
    }
    auto result = format(data);
    if(result.size() > destCount)
        return FORMAT_BUFFER_TOO_SMALL;
    strcpy_s(dest, destCount, result.c_str());
    return FORMAT_SUCCESS;
}

static FORMATRESULT formatcpy_s(char* dest, size_t destCount, const char* source)
{
    switch(strncpy_s(dest, destCount, source, _TRUNCATE))
    {
    case 0:
        return FORMAT_SUCCESS;
    case ERANGE:
    case STRUNCATE:
        return FORMAT_BUFFER_TOO_SMALL;
    default:
        return FORMAT_ERROR;
    }
}

void FormatFunctions::Init()
{
    Register("mem", [](char* dest, size_t destCount, int argc, char* argv[], duint addr, void* userdata)
    {
        return memoryFormatter<unsigned char>(dest, destCount, argc, argv, addr, [](std::vector<unsigned char> & data)
        {
            return StringUtils::ToHex(data.data(), data.size());
        });
    });

    Register("ascii", [](char* dest, size_t destCount, int argc, char* argv[], duint addr, void* userdata)
    {
        return memoryFormatter<unsigned char, 512>(dest, destCount, argc, argv, addr, [](std::vector<unsigned char> & data)
        {
            String result;
            result.reserve(data.size());
            for(auto & ch : data)
            {
                if(isprint(ch))
                    result.push_back(char(ch));
                else
                    result.push_back('?');
            }
            return result;
        });
    });

    Register("ansi", [](char* dest, size_t destCount, int argc, char* argv[], duint addr, void* userdata)
    {
        return memoryFormatter<char, 512>(dest, destCount, argc, argv, addr, [](std::vector<char> & data)
        {
            if(data.empty() || data.back() != '\0')
                data.push_back('\0');
            return StringUtils::LocalCpToUtf8(data.data());
        });
    });

    Register("utf8", [](char* dest, size_t destCount, int argc, char* argv[], duint addr, void* userdata)
    {
        return memoryFormatter<char, 512>(dest, destCount, argc, argv, addr, [](std::vector<char> & data)
        {
            if(data.empty() || data.back() != '\0')
                data.push_back('\0');
            return String(data.data());
        });
    });

    Register("utf16", [](char* dest, size_t destCount, int argc, char* argv[], duint addr, void* userdata)
    {
        return memoryFormatter<wchar_t, 512>(dest, destCount, argc, argv, addr, [](std::vector<wchar_t> & data)
        {
            if(data.empty() || data.back() != L'\0')
                data.push_back(L'\0');
            return StringUtils::Utf16ToUtf8(data.data());
        });
    });

    Register("winerror", [](char* dest, size_t destCount, int argc, char* argv[], duint code, void* userdata)
    {
        std::vector<wchar_t> helpMessage(destCount);
        String errName = ErrorCodeToName((unsigned int)code);
#ifdef _WIN64
        if((code >> 32) != 0)  //Data in high part: not an error code
        {
            errName = StringUtils::sprintf("%p", code);
            if(destCount < errName.size() + 1)
                return FORMAT_BUFFER_TOO_SMALL;
            else
            {
                memcpy(dest, errName.c_str(), errName.size() + 1);
                return FORMAT_SUCCESS;
            }
        }
#endif //_WIN64
        if(errName.size() == 0)
            errName = StringUtils::sprintf("%08X", DWORD(code));

        return formatErrorMsg(GetModuleHandleW(L"kernel32.dll"), errName, DWORD(code), dest, destCount);
    });

    Register("ntstatus", [](char* dest, size_t destCount, int argc, char* argv[], duint code, void* userdata)
    {
        std::vector<wchar_t> helpMessage(destCount);
        String errName = NtStatusCodeToName((unsigned int)code);
        if(errName.size() == 0)
            errName = StringUtils::sprintf("%08X", DWORD(code));

        return formatErrorMsg(GetModuleHandleW(L"ntdll.dll"), errName, DWORD(code), dest, destCount);
    });

    Register("disasm", [](char* dest, size_t destCount, int argc, char* argv[], duint addr, void* userdata)
    {
        const char* result = nullptr;
        BASIC_INSTRUCTION_INFO info;
        if(!disasmfast(addr, &info, true))
            result = "???";
        else
            result = info.instruction;
        return formatcpy_s(dest, destCount, result);
    });

    Register("modname", [](char* dest, size_t destCount, int argc, char* argv[], duint addr, void* userdata)
    {
        char mod[MAX_MODULE_SIZE] = "";
        if(!ModNameFromAddr(addr, mod, true))
            return FORMAT_ERROR;
        return formatcpy_s(dest, destCount, mod);
    });

    Register("bswap", [](char* dest, size_t destCount, int argc, char* argv[], duint addr, void* userdata)
    {
        duint size = sizeof(duint);
        if(argc > 1 && !valfromstring(argv[1], &size))
        {
            strcpy_s(dest, destCount, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Invalid argument...")));
            return FORMAT_ERROR_MESSAGE;
        }
        if(size > sizeof(duint) || size == 0)
        {
            strcpy_s(dest, destCount, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Invalid size...")));
            return FORMAT_ERROR_MESSAGE;
        }
        auto data = (unsigned char*)&addr;
        String result;
        for(duint i = 0; i < size; i++)
            result += StringUtils::sprintf("%02X", data[i]);
        return formatcpy_s(dest, destCount, result.c_str());
    });

    Register("comment", [](char* dest, size_t destCount, int argc, char* argv[], duint addr, void* userdata)
    {
        char comment[MAX_COMMENT_SIZE] = "";
        if(DbgGetCommentAt(addr, comment))
        {
            if(comment[0] == '\1') //automatic comment
                return formatcpy_s(dest, destCount, comment + 1);
            else
                return formatcpy_s(dest, destCount, comment);
        }
        return FORMAT_ERROR;
    });

    Register("label", [](char* dest, size_t destCount, int argc, char* argv[], duint addr, void* userdata)
    {
        char label[MAX_LABEL_SIZE] = "";
        if(DbgGetLabelAt(addr, SEG_DEFAULT, label))
            return formatcpy_s(dest, destCount, label);
        return FORMAT_ERROR;
    });
}

bool FormatFunctions::Register(const String & type, const CBFORMATFUNCTION & cbFunction, void* userdata)
{
    if(!isValidName(type))
        return false;
    EXCLUSIVE_ACQUIRE(LockFormatFunctions);
    if(mFunctions.count(type))
        return false;
    Function f;
    f.type = type;
    f.cbFunction = cbFunction;
    f.userdata = userdata;
    mFunctions[type] = f;
    return true;
}

bool FormatFunctions::RegisterAlias(const String & name, const String & alias)
{
    EXCLUSIVE_ACQUIRE(LockFormatFunctions);
    auto found = mFunctions.find(name);
    if(found == mFunctions.end())
        return false;
    if(!Register(alias, found->second.cbFunction, found->second.userdata))
        return false;
    found->second.aliases.push_back(alias);
    return true;
}

bool FormatFunctions::Unregister(const String & name)
{
    EXCLUSIVE_ACQUIRE(LockFormatFunctions);
    auto found = mFunctions.find(name);
    if(found == mFunctions.end())
        return false;
    auto aliases = found->second.aliases;
    mFunctions.erase(found);
    for(const auto & alias : found->second.aliases)
        Unregister(alias);
    return true;
}

bool FormatFunctions::Call(std::vector<char> & dest, const String & type, std::vector<String> & argv, duint value)
{
    SHARED_ACQUIRE(LockFormatFunctions);
    auto found = mFunctions.find(type);
    if(found == mFunctions.end())
        return false;

    std::vector<char*> argvn(argv.size());
    for(size_t i = 0; i < argv.size(); i++)
        argvn[i] = (char*)argv[i].c_str();

    const auto & f = found->second;
    dest.resize(512, '\0');
fuckthis:
    auto result = f.cbFunction(dest.data(), dest.size() - 1, int(argv.size()), argvn.data(), value, f.userdata);
    if(result == FORMAT_BUFFER_TOO_SMALL)
    {
        dest.resize(dest.size() * 2, '\0');
        goto fuckthis;
    }
    return result != FORMAT_ERROR;
}

bool FormatFunctions::isValidName(const String & name)
{
    if(!name.length())
        return false;
    if(!(name[0] == '_' || isalpha(name[0])))
        return false;
    for(const auto & ch : name)
        if(!(isalnum(ch) || ch == '_' || ch == '.'))
            return false;
    return true;
}

没看懂,修改哪?
evea 发表于 2023-4-18 16:59
本帖最后由 evea 于 2023-4-18 17:11 编辑



试了一下这个:
RAX寄存器字符串:{s:RAX}RBX寄存器字符串:{s:RBX} RCX寄存器字符串:{s:RCX}RDX寄存器字符串:{s:RDX}RBP寄存器字符串:{s:RBP}RSP寄存器字符串:{s:RSP}RSI寄存器字符串:{s:RSI}RDI寄q存器字符串:{s:RDI}R8寄存器字符串:{s:R8}R9寄存器字符串:{s:R9}R10寄存器字符串:{s:R10}R11寄存器字符串:{s:r11}R12寄存器字符串:{s:R12}R13寄存器字符串:{s:R13}R14寄存器字符串:{s:R14}R15寄存器字符串:{s:R15}

调了一下  发现问题了  
s 和 utf8.utf16 走的的流程不一样
cbGenericBreakpoint+549
handleFormatStringInline  
   含@ printComplexValue
   否则 printValue
       char string[MAX_STRING_SIZE] = ""; // MAX_STRING_SIZE 在 bridgemain.h
       case StringValueType::String:
            if(disasmgetstringatwrapper(valuint, string, false))
                return string;

utf8  utf16 走 printComplexValue  按照之前的修改 是可以的
s 走的是printValue  这里没法patch了   只能修改 MAX_STRING_SIZE  编译


另外:
    记录断点输入 的长度  到最后 最长255BYTE   所以上面 R8 开始之后是没有的   
这个可能是UI处理了
BREAKPOINT 中也处理了
[Asm] 纯文本查看 复制代码
struct BREAKPOINT
{
    duint addr;                                       // address of the breakpoint (rva relative to base of mod)
    bool enabled;                                     // whether the breakpoint is enabled
    bool singleshoot;                                 // whether the breakpoint should be deleted on first hit
    bool active;                                      // whether the breakpoint is active or not
    bool silent;                                      // whether the breakpoint diplays a default message when hit
    unsigned short oldbytes;                          // original bytes (for software breakpoitns)
    BP_TYPE type;                                     // breakpoint type
    DWORD titantype;                                  // type passed to titanengine
    char name[MAX_BREAKPOINT_SIZE];                   // breakpoint name
    char mod[MAX_MODULE_SIZE];                        // module name
    char breakCondition[MAX_CONDITIONAL_EXPR_SIZE];   // condition to stop. If true, debugger halts.
    char logText[MAX_CONDITIONAL_TEXT_SIZE];          // text to log.
    char logCondition[MAX_CONDITIONAL_EXPR_SIZE];     // condition to log
    char commandText[MAX_CONDITIONAL_TEXT_SIZE];      // script command to execute.
    char commandCondition[MAX_CONDITIONAL_EXPR_SIZE]; // condition to execute the command
    uint32 hitcount;                                  // hit counter
    bool fastResume;                                  // if true, debugger resumes without any GUI/Script/Plugin interaction.
    duint memsize;                                    // memory breakpoint size (not implemented)
};


所以 MAX_CONDITIONAL_TEXT_SIZE      也需要改 一下
 楼主| 冥界3大法王 发表于 2023-3-30 11:45
只能把“寄存器字符串”这几个字干掉了。
问题2 : 怎么用脚本判断 寄存器是字符串呢?
问题3:哪个命令可以,只记录,不中断?
成熟的美羊羊 发表于 2023-3-30 12:36
用lyscript,增强x96dbg脚本功能。
evea 发表于 2023-3-30 17:31
32位的:
path  X32DBG.dll

搜索 utf16 utf8
  找到虚表
  std::_Func_impl<std::_Callable_obj<_lambda_xxxxxx_,0>,std::allocator<std::_Func_class<enum FORMATRESULT,char *,unsigned int,int,char * *,unsigned long,void *>>,enum FORMATRESULT,char *,unsigned int,int,char * *,unsigned long,void *>::`vftable';
  第二个函数为(::_Do_call) 找到memoryFormatter_XXXX具体实现函数 在函数里修改即可
  =>> MOV EAX, 0x200  ==> MOV EAX, 0x2000(最大1024 * 1024 * 10 //10MB max)
  对应的代码  formatfunctions.cpp
  可以看看特征码能不能找到:
  55 8B EC 6A ?? 68 ?? ?? ?? ?? 64 A1 ?? ?? ?? ?? 50 83 EC ?? A1 ?? ?? ?? ?? 33 C5 89 45 ?? 56 57 50 8D 45 ?? 64 A3 ?? ?? ?? ?? 83 7D ?? ?? B8 00 02 00 00

免费评分

参与人数 1吾爱币 +4 热心值 +1 收起 理由
冥界3大法王 + 4 + 1 谢谢@Thanks!

查看全部评分

evea 发表于 2023-3-30 17:42
本帖最后由 evea 于 2023-3-30 17:45 编辑

3   感觉 bpcon + bplog 可以实现    感觉!!没试过


因为 我在x32dbg 上复制条件断点 会复制出以下信息

bpcnd 0041770C, "0"
bpl 0041770C, "addr {[esp]}   ssss {s:edx}"
bplogcondition 0041770C, "1"
SetBreakpointCommand 0041770C, ""
SetBreakpointCommandCondition 0041770C, ""
SetBreakpointFastResume 0041770C, 0
SetBreakpointSilent 0041770C, 1
SetBreakpointSingleshoot 0041770C, 0

免费评分

参与人数 1吾爱币 +2 热心值 +1 收起 理由
冥界3大法王 + 2 + 1 用心讨论,共获提升!

查看全部评分

 楼主| 冥界3大法王 发表于 2023-3-30 18:51
本帖最后由 冥界3大法王 于 2023-3-30 19:46 编辑
evea 发表于 2023-3-30 17:31
32位的:
path  X32DBG.dll
@evea
牛逼我的哥,我去修改源代码
不知还有啥方法内简单的解决。

下面说的方案,我也得试试
bpcnd 0041770C, "0"
bpl 0041770C, "addr {[esp]}   ssss {s:edx}"
bplogcondition 0041770C, "1"
SetBreakpointCommand 0041770C, ""
SetBreakpointCommandCondition 0041770C, ""
SetBreakpointFastResume 0041770C, 0
SetBreakpointSilent 0041770C, 1
SetBreakpointSingleshoot 0041770C, 0
妈啊,这代码行也太多点吧,用Delphi得写8行一个地址里。

 楼主| 冥界3大法王 发表于 2023-3-30 21:08
evea 发表于 2023-3-30 17:42
3   感觉 bpcon + bplog 可以实现    感觉!!没试过

经测试分行打来的代码脚本没有效果。
evea 发表于 2023-3-31 11:19
[C++] 纯文本查看 复制代码
Register("ascii", [](char* dest, size_t destCount, int argc, char* argv[], duint addr, void* userdata)
    {
        return memoryFormatter<unsigned char, 512>(dest, destCount, argc, argv, addr, [](std::vector<unsigned char> & data)
        {
            String result;
            result.reserve(data.size());
            for(auto & ch : data)
            {
                if(isprint(ch))
                    result.push_back(char(ch));
                else
                    result.push_back('?');
            }
            return result;
        });
    });

    Register("ansi", [](char* dest, size_t destCount, int argc, char* argv[], duint addr, void* userdata)
    {
        return memoryFormatter<char, 512>(dest, destCount, argc, argv, addr, [](std::vector<char> & data)
        {
            if(data.empty() || data.back() != '\0')
                data.push_back('\0');
            return StringUtils::LocalCpToUtf8(data.data());
        });
    });

    Register("utf8", [](char* dest, size_t destCount, int argc, char* argv[], duint addr, void* userdata)
    {
        return memoryFormatter<char, 512>(dest, destCount, argc, argv, addr, [](std::vector<char> & data)
        {
            if(data.empty() || data.back() != '\0')
                data.push_back('\0');
            return String(data.data());
        });
    });

    Register("utf16", [](char* dest, size_t destCount, int argc, char* argv[], duint addr, void* userdata)
    {
        return memoryFormatter<wchar_t, 512>(dest, destCount, argc, argv, addr, [](std::vector<wchar_t> & data)
        {
            if(data.empty() || data.back() != L'\0')
                data.push_back(L'\0');
            return StringUtils::Utf16ToUtf8(data.data());
        });
    });




把  memoryFormatter<XXXXX, 512>  中的512 改成你想要的大小就可以

免费评分

参与人数 1吾爱币 +4 热心值 +1 收起 理由
冥界3大法王 + 4 + 1 改完了,没有效果啊。

查看全部评分

evea 发表于 2023-3-31 11:39
本帖最后由 evea 于 2023-3-31 11:46 编辑
冥界3大法王 发表于 2023-3-30 21:08
经测试分行打来的代码脚本没有效果。

我刚刚试出来了

[C++] 纯文本查看 复制代码
bp 00404E3C
bpl 00404E3C, "addr {[esp]}  LstrAsg : {s:edx}"
bpcnd 00404E3C, "0"
g



这样可以下不暂定的记录断点  
如果先前没有断点
    必须要有先bp 00404E3C
    否则两外两条那条在先都会提示 断点不存在
先前有断点
    可以没有 bp 00404E3C

免费评分

参与人数 1热心值 +1 收起 理由
冥界3大法王 + 1 谢谢@Thanks!

查看全部评分

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-25 23:58

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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