分类 技术 下的文章

注意:/data/local/tmp目录不小心被删除了,只要改owner和访问权限是够的,这是个特殊目录,还需要改selinux权限

chcon -R u:object_r:shell_data_file:s0 /data/local/tmp

frida-gadget持久化

未ROOT设备采用smail增加System.loadlibray("frida-gadget")方式注入,缺点就是打包检测兼容问题。

ROOT设备如果有类似libmsaoaidsec线程检测
hook dlopen查看加载顺序,找个libmsaoaidsec之前加载的so注入改导入表。

pip install lief
#!/usr/bin/env python3
import lief
libnative = lief.parse("libmmkv.so")
libnative.add_library("gad.so")
libnative.write("libmmkv.so")

adb shell pm path 包名
找到路径将gad.so和libmmkv.so放进lib/arm64
并且创建gad.config.so启动自动加载js

{
    "interaction": {
        "type": "script",
        "path": "/data/local/tmp/hook.js"
    }
}

方法一:

1,第一步下载winehq9.0源码:

https://www.winehq.org/

1,编译wine 32位和64位共存

(这一步很重要,如果你想装64位微信就得有64位wine容器,但只编译64位版本因为缺少system32里面文件也会安装不起来)

  • 创建两文件夹wine32 wine64 将源码解压2份放入两个文件夹
  • 修改两文件夹源码dlls/user32/win.c文件

      cs.lpszClass      = className;
      cs.dwExStyle      = exStyle;
      //-------如下是增加的
      if (exStyle == 0x080800a0) // WeChat/WxWork shadow hwnd
      {
          FIXME("hack %x\n", cs.dwExStyle);
          return NULL;
      }
      if (exStyle == 0x000800a0) // Netease Cloudmusic shadow wnd
      {
          FIXME("hack %x\n", cs.dwExStyle);
          return NULL;
      }
      //-------上面是增加的
      return wow_handlers.create_window( &cs, className, instance, TRUE );
    }
    sudo dpkg --add-architecture i386
    sudo apt -y install build-essential && sudo apt -y install libc6-dev:i386 && sudo apt-get -y install gcc-multilib
    sudo apt-get install flex bison libx11-dev:i386
    sudo apt-get install libfreetype-dev:i386
    sudo apt-get install libx11-dev
    sudo apt-get install libfreetype-dev
    
    export C_INCLUDE_PATH=/usr/include/freetype2
    export CPLUS_INCLUDE_PATH=/usr/include/freetype2
    
    cd wine64
    ./configure --enable-win64
    make -j 8
    
    cd ../wine32
    ./configure --with-wine64=../wine64
    (编译32位wine时通过--with-wine64参数指定了已编译完成的wine64位的目录,这样编译32位wine时,程序会注入64位版本处理32位程序所需的库。)
    make -j 8
    
    sudo make DESTDIR=/opt/wine install
    cd ../wine64
    sudo make DESTDIR=/opt/wine install

    如上一定注意编译和安装顺便,编译要先编译64位,再编译32位,安装的话先安装32位再安装64位

3,配置安装

cd /opt/wine/usr/local/bin
(可以wine安装完找不到路径就执行这句,可有可无)
export WINEARCH=win64
(指定架构,好像老版本才用,可有可无)
export WINEPREFIX=~/.wine
(配置容器路径)
winecfg
(初始化,改缩放192)
sudo apt install winetricks
(安装wine搭档)
winetricks
(界面选择安装riched20 riched32)
winecfg
(函数库 riched20 riched32都是原装先于内建,wechatocr.exe停用)
env WINEPREFIX=~/.wine /opt/wine/usr/local/bin/wine64 ~/Downloads/WeChatSetup.exe

方法二:

X api
第一种同样是隐藏窗体,但是在X的层面进行的操作. 然而网上使用的方法大多是错误的, 要么是漏杀, 要么是错杀. 我写了一个正确的程序, 可以正确的隐藏阴影框, 同时不影响各个菜单.

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <xcb/xcb.h>
#include <xcb/xcb_aux.h>
#include <xcb/xcb_event.h>
#include <xcb/xcb_icccm.h>
#include <xcb/xproto.h>

static xcb_connection_t *conn;
static xcb_screen_t *scr;
static xcb_atom_t atom;

void init_atom() {
  // Get `_NET_WM_NAME` atom
  const char *atom_name = "_NET_WM_NAME";
  xcb_intern_atom_cookie_t atom_cookie =
      xcb_intern_atom(conn, true, strlen(atom_name), atom_name);
  xcb_intern_atom_reply_t *atom_reply =
      xcb_intern_atom_reply(conn, atom_cookie, NULL);
  if (!atom_reply) {
    fprintf(stderr, "_NET_WM_NAME atom not found, WTF?\n");
    return;
  }
  atom = atom_reply->atom;
  free(atom_reply);
}

void handle_wechat(xcb_window_t window) {
  // Get value of `_NET_WM_NAME`
  xcb_icccm_get_text_property_reply_t prop;
  if (!xcb_icccm_get_text_property_reply(
          conn, xcb_icccm_get_text_property(conn, window, atom), &prop, NULL)) {
    fprintf(stderr, "Can't get _NET_WM_NAME property\n");
    return;
  }
  if (prop.name_len) {
    printf("Normal window with name: %.*s\n", prop.name_len, prop.name);
    return;
  }
  // If `_NET_WM_NAME` is empty, check if this windows accept input
  xcb_icccm_wm_hints_t hints;
  if (!xcb_icccm_get_wm_hints_reply(conn, xcb_icccm_get_wm_hints(conn, window),
                                    &hints, NULL)) {
    fprintf(stderr, "Can't get WM_HINTS property\n");
    return;
  }
  if ((hints.flags & XCB_ICCCM_WM_HINT_INPUT) && hints.input) {
    printf("Normal dialog without name\n");
    return;
  }
  printf("Black shadow window, unmap it!\n");
  xcb_unmap_window(conn, window);
  return;
}

bool is_wechat(xcb_window_t window) {
  xcb_get_property_cookie_t cookie = xcb_get_property(
      conn, 0, window, XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 0, 32);
  xcb_get_property_reply_t *reply = xcb_get_property_reply(conn, cookie, NULL);
  if (!reply) {
    return false;
  }
  int len = xcb_get_property_value_length(reply);
  if (!len) {
    free(reply);
    return false;
  }
  char *property = (char *)xcb_get_property_value(reply);
  printf("0x%0x8: WM_CLASS= %.*s\n", window, len, property);
  bool result = false;
  if (!strcmp(property, "wechat.exe")) {
    printf("Wechat found!\n");
    result = true;
  }
  free(reply);
  return result;
}

int main(int argc, char **argv) {
  conn = xcb_connect(NULL, NULL);
  if (xcb_connection_has_error(conn)) {
    fprintf(stderr, "Failed to connect to the X server\n");
    exit(1);
  }
  scr = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
  if (!scr) {
    fprintf(stderr, "Failed to get X screen\n");
    exit(2);
  }

  uint32_t val[] = {XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY};
  xcb_change_window_attributes(conn, scr->root, XCB_CW_EVENT_MASK, val);

  init_atom();

  while (1) {
    xcb_aux_sync(conn);
    xcb_generic_event_t *e = xcb_wait_for_event(conn);
    if (XCB_EVENT_RESPONSE_TYPE(e) == XCB_MAP_NOTIFY) {
      xcb_map_notify_event_t *map = (xcb_map_notify_event_t *)e;
      if (is_wechat(map->window)) {
        handle_wechat(map->window);
      }
    }
    free(e);
  }

  if (conn) {
    xcb_disconnect(conn);
  }
  return 0;
}

编译方法:

gcc xwechathide.c -lxcb -lxcb-util -lxcb-icccm -o xwechathide

转至https://12101111.github.io/block-wine-wechat-black-window/

#!/bin/bash

voicefile=/usr/share/sounds/sound-icons/cembalo-6.wav

if [ ! -f $voicefile ];then
    echo "声音文件不存在"
    exit 0
fi

dbus-monitor 'type=method_call, interface=org.freedesktop.Notifications, member=Notify' | grep --line-buffered -E '^\s*string "QQ|Icalingua\+\+"$' | while read test; do paplay $voicefile;done

x64 inlinehook调用OutputDebugString一直崩溃, x64dbg跟踪发现崩溃在:

<ntdll.RtlCaptureContext>            
| 48:9C                              | pushfq      
| 8C49 38                            | mov word ptr ds:[rcx+38],cs                       
| 8C59 3A                            | mov word ptr ds:[rcx+3A],ds                       
| 8C41 3C                            | mov word ptr ds:[rcx+3C],es                       
| 8C51 42                            | mov word ptr ds:[rcx+42],ss                       
| 8C61 3E                            | mov word ptr ds:[rcx+3E],fs                       
| 8C69 40                            | mov word ptr ds:[rcx+40],gs                       
| 48:8941 78                         | mov qword ptr ds:[rcx+78],rax                     
| 48:8989 80000000                   | mov qword ptr ds:[rcx+80],rcx                     
| 48:8991 88000000                   | mov qword ptr ds:[rcx+88],rdx                     
| 48:8999 90000000                   | mov qword ptr ds:[rcx+90],rbx                     
| 48:8D4424 10                       | lea rax,qword ptr ss:[rsp+10]                     
| 48:8981 98000000                   | mov qword ptr ds:[rcx+98],rax                     
| 48:89A9 A0000000                   | mov qword ptr ds:[rcx+A0],rbp                     
| 48:89B1 A8000000                   | mov qword ptr ds:[rcx+A8],rsi                     
| 48:89B9 B0000000                   | mov qword ptr ds:[rcx+B0],rdi                     
| 4C:8981 B8000000                   | mov qword ptr ds:[rcx+B8],r8                      
| 4C:8989 C0000000                   | mov qword ptr ds:[rcx+C0],r9                      
| 4C:8991 C8000000                   | mov qword ptr ds:[rcx+C8],r10                     
| 4C:8999 D0000000                   | mov qword ptr ds:[rcx+D0],r11                     
| 4C:89A1 D8000000                   | mov qword ptr ds:[rcx+D8],r12                     
| 4C:89A9 E0000000                   | mov qword ptr ds:[rcx+E0],r13                     
| 4C:89B1 E8000000                   | mov qword ptr ds:[rcx+E8],r14                     
| 4C:89B9 F0000000                   | mov qword ptr ds:[rcx+F0],r15                     
| 0FAE81 00010000                    | fxsave ds:[rcx+100]                 <<崩溃行 

查资料得:
对xmm操作是需要16byte对齐, 当rcx没有16对齐时就会报错,也就是 fxsave操作地址必须16位对齐,而rcx是通过sub rsp得到,所以调用OutputDebugString时,RSP必须为0x10的倍数地址。

所以通过自己sub rsp 8x(可为8倍数), 再调用OutputDebugString,结尾add rsp 8x调整堆栈平衡解决。

头大,x64存在一些x86不用考虑的问题,害我研究了一整天。

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Terminal Server/Wds/rdpwd/Tds/tcp]
"PortNumber"=dword:0000e089

[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Terminal Server/WinStations/RDP-Tcp]
"PortNumber"=dword:0000e089

reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\Wds\rdpwd\Tds\tcp" /v PortNumber /t reg_dword /d 57481 /f

reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v PortNumber /t reg_dword /d 57481 /f

net stop TermService

net start TermService