有没有一种应用程序可以在不使用消息框 API 的情况下显示消息的方法?

逆向工程 视窗 补丁反转 德尔福
2021-06-13 06:45:45

我有一个应用程序,用于在单击“确定”按钮后显示一条消息“正在处理”,然后显示另一条消息“完成”,但现在没有了。所以我把它倒过来看看发生了什么,但结果是搜索字符串的方式不起作用,所以我搜索了messageboxAPI,但我发现了messageboxA两次,MessageboxW一次,它们似乎都没有用于那个。

所以,我想知道是否有可能在不使用MessageBoxAPI 的情况下显示消息,或者甚至 DLL 可以在没有 API 的情况下显示消息?请帮忙

3个回答
  1. 首先你需要确定它是否是windows消息框。

    消息框(自定义/标准win32 /系统字符串编译)中是什么类型的消息如果可能的话,屏幕截图也会很好(所以我们可以看到更多......)如果你可以让它在一些测试机器上工作然后检查消息框CLASS_ID它可以显示它是 Windows 消息框还是自定义VCL形式,只是看起来像它...你可以获得类标识码

    但它被删除了,你在 SO 上没有足够的代表来查看它,所以这里复制了源代码(VCL C++,所以如果你没有Borland C++,你只需要移植到Pascal):

    //---------------------------------------------------------------------------
    //--- Windows ver: 1.1 ------------------------------------------------------
    //---------------------------------------------------------------------------
    HWND getwindow(HWND hnd0,AnsiString nam,AnsiString cls="")
        {
        int i,l,ln=nam.Length(),lc=cls.Length(),e;
        char txt[256];
        HWND hnd1;
        if (hnd0==NULL) hnd1=GetTopWindow(hnd0);
        else            hnd1=GetWindow(hnd0,GW_HWNDNEXT);
        for (;;)
            {
            e=1;
            if (hnd1==hnd0) break;
            if (hnd1==NULL) break;
            l=GetWindowText(hnd1,txt,256);
            if (e) { if (l>ln) l=ln; if (l<ln) e=0; else for (i=0;i<l;i++) if (txt[i]!=nam[i+1]) { e=0; break; } }
            l=RealGetWindowClass(hnd1,txt,256);
            if (e) { if (l>lc) l=lc; if (l<lc) e=0; else for (i=0;i<l;i++) if (txt[i]!=cls[i+1]) { e=0; break; } }
            if (e) return hnd1;
            hnd0=hnd1;
            hnd1=GetWindow(hnd0,GW_HWNDNEXT);
            }
        return NULL;
        };
    //---------------------------------------------------------------------------
    HWND getsubwindow(HWND hndp,HWND hnd0,AnsiString nam,AnsiString cls="")
        {
        int i,l,ln=nam.Length(),lc=cls.Length(),e;
        char txt[256];
        HWND hnd1;
        if (hnd0==NULL) hnd1=GetTopWindow(hnd0);
        else            hnd1=GetWindow(hnd0,GW_HWNDNEXT);
        for (;;)
            {
            e=1;
            if (hnd1==hnd0) break;
            if (hnd1==NULL) break;
            if (GetParent(hnd1)!=hndp) e=0;
            l=GetWindowText(hnd1,txt,256);
            if (e) { if (l>ln) l=ln; if (l<ln) e=0; else for (i=0;i<l;i++) if (txt[i]!=nam[i+1]) { e=0; break; } }
            l=RealGetWindowClass(hnd1,txt,256);
            if (e) { if (l>lc) l=lc; if (l<lc) e=0; else for (i=0;i<l;i++) if (txt[i]!=cls[i+1]) { e=0; break; } }
            if (e) return hnd1;
            hnd0=hnd1;
            hnd1=GetWindow(hnd0,GW_HWNDNEXT);
            }
        return NULL;
        };
    //---------------------------------------------------------------------------
    bool getwindows(HWND &hnd,AnsiString &nam,AnsiString &cls)
        {
        int i,l;
        char txt[256];
        HWND hnd0=hnd;
        nam=""; cls="";
        if (hnd0==NULL) hnd=GetTopWindow(hnd0);
        else            hnd=GetWindow(hnd0,GW_HWNDNEXT);
        if (hnd==hnd0) { hnd=NULL; return false; }
        if (hnd==NULL) { hnd=NULL; return false; }
        l=GetWindowText(hnd,txt,256);       for (i=0;i<l;i++) nam+=txt[i];
        l=RealGetWindowClass(hnd,txt,256);  for (i=0;i<l;i++) cls+=txt[i];
        return true;
        };
    //---------------------------------------------------------------------------
    //---------------------------------------------------------------------------
    //---------------------------------------------------------------------------

使用BDS2006 Turbo C++编写并使用VCL,因此您需要将其转换为您的语言。实际上它只AnsiStringVCL使用所以只需将其更改为您拥有的任何字符串。基于WinAPI,所以包括“Windows.h”

以下是一些用法示例:

    HANDLE hnd,hnd0;
    AnsiString nam,cls;
    AnsiString s,t="";
    for (hnd=NULL;;)
        {
        if (!getwindows(hnd,nam,cls)) break;    // get hnd,name and class
        hnd0=GetParent(hnd);            // get parent hnd
        if (hnd0!=Application->Handle) continue;// filter out unwanted windows
        // here process found window or add it to list or what ever
        // for example add to memo->Lines->Add(...) so you obtain a list of all windows ...
        s=AnsiString().sprintf("%X",hnd); while (s.Length()< 8) s="0"+s; t+=s+"h ";
        s=cls;                            while (s.Length()<32) s=s+" "; t+=s+" ";
        s=nam;                            while (s.Length()<32) s=s+" "; t+=s+"\r\n";
        }
    mm_log->Text=t; // just my memo

这里有几行未过滤的输出:

    Handle:   Class_ID:                        Name
    0003060Ch TTokenWindow                     CodeParamWindow                 
    00030374h ComboLBox                                                        
    000100F8h tooltips_class32                                                 
    000100FAh TaskListThumbnailWnd                                             
    000100E6h tooltips_class32                                                 
    000100E8h tooltips_class32                                                 
    000100ECh tooltips_class32                                                 
    000100EEh tooltips_class32                                                 
    000100D0h tooltips_class32                                                 
    000100E4h tooltips_class32                                                 
    000100C8h Button                           Start                           
    00030118h tooltips_class32                                                 
    0003013Eh tooltips_class32                                                 
    00040122h tooltips_class32                                                 
    00090102h tooltips_class32                                                 
    000100C2h Shell_TrayWnd                                                    
    000303ECh TaskSwitcherOverlayWnd                                           
    00010240h IME                              Default IME                     
    0001023Eh TaskSwitcherWnd                  Task Switching                  
    00030376h ComboLBox                                                        
    000403A0h Auto-Suggest Dropdown                                            
    00010108h CiceroUIWndFrame                 CiceroUIWndFrame                
    000100C6h MSCTFIME UI                      MSCTFIME UI                     
    000100C0h IME                              Default IME                     
    00010158h tooltips_class32                                                 
    00010246h ATL:000007FEF0EF52C0             Network Flyout                  
    00010180h CDA Server Class                 Administrator : CDA Server      
    00010182h IME                              Default IME                     
    0001008Ch CiceroUIWndFrame                 CiceroUIWndFrame                
    0001008Ah CiceroUIWndFrame                 TF_FloatingLangBar_WndTitle     
    000303CEh tooltips_class32                                                 
    0003061Eh TForm1                           Project Euler                   
    00090566h TApplication                     Project1                        
    0003061Ah TPUtilWindow                                                     
    00050610h IME                              Default IME                     
    00090386h MSCTFIME UI                      MSCTFIME UI                     
    00210408h IME                              Default IME                     
    000B0416h TEditWindow                      Unit1.cpp                       
    0007057Ch TWatchWindow                     Watch List                      
    000105B2h TTabDockHostForm                 Project1.bdsproj - Project Manager

正如你所看到的,会有很多句柄(所有的视觉组件都像窗口一样,所以你需要过滤掉很多东西......例如找到hnd你的消息框应用程序的 。然后只显示具有相同 parrent 的句柄hnd0

例如,我刚刚创建了一个消息框来获取Class_ID

    int ret=MessageDlg("Test message",mtCustom,TMsgDlgButtons(mrOk),-1); // cls = "TMessageForm"

要获得父句柄,您需要在未过滤的列表中搜索 class TApplicationApplication->Handle改用了,因为我直接在同一个应用程序中测试了它。

  1. 如果消息框是原生的 win32

    那么这并不一定意味着应用程序直接调用winapi很可能它使用了一些VCL封装来代替。因此,任何消息框函数名称Delphi IDE帮助都是棕色的……测试它们并查看Class_ID是否与您的应用程序匹配……

  2. 如果消息框不是原生的 win32

    那么它很可能是正常的VCL窗口。类名就是Delphi窗口类的名称,TForm1. 窗口的名称通常是它的,Caption而对于 App,则是 exe 文件名。在这种情况下,显示对话框是不同的:

    • 设置位置Left,Top,Width,Height或调用SetBounds()
    • 设置消息可以是TLabel,TEdit,...TextCaption属性或直接呈现在 上Canvas
    • 设置Visible=true或使用ShowWindow,ShowModal...

    所以你知道要寻找什么......

  3. 文本

    对于多语言应用程序,文本通常在一些*.ini*.dll文件中。在的情况下,DLLDLL可以被压缩或加密,从而它是不容易看到。尝试在文件名中搜索带有语言的文件。

如果您有更多信息,请告诉我,希望对您有所帮助。

MessageBox API 只是创建一个窗口对话框并在消息循环中旋转直到它关闭。

程序可以在不使用 MessageBox 的情况下自行完成此操作,您可以查找对CreateDialogCreateWindow 的调用

尝试在 CFF Explorer 的十六进制编辑器中打开可执行文件并搜索这些字符串,如果找不到它们,那么我建议您寻找有关在可执行文件中查找隐藏代码的帮助。我认为程序员有时可以隐藏代码部分,也可以加密或隐藏字符串。找到隐藏的代码部分,然后再次查找 API。