[记录] NodeJs调用nwjs模块的分析 | 祭夜の咖啡馆
  • 欢迎光临,这个博客颜色有点多

[记录] NodeJs调用nwjs模块的分析

猿之力 msojocs 1个月前 (10-12) 124次浏览 已收录 1个评论 扫描二维码
文章目录[隐藏]

前言

本篇文章基于nwjs0.54.1以及node16.4.0

之前尝试 NTQQ 使用 NodeJs 运行,想起wechat-web-devtools-linux有个skyline模块;
这个模块是运行在nwjs环境的,试试看能不能换成nodejs。

[Windows] 分析使用nodejs启动NTQQ

文章目录[隐藏] 前言 分析 伪造QQNT.dll 总结 前言 上篇实现了Linux平台使用nodejs启动的 […]

实践

把node.dll和nw.dll都做了转发,但是启动会崩溃。

崩溃代码(from ida):

__int64 __fastcall sub_7FFC1E826EE2(__int64 *a1)
{
  __int64 v2; // rdi
  __int64 v3; // rax
  __int64 v4; // rax
  _QWORD *v5; // rcx
  _QWORD *v7; // [rsp+28h] [rbp-40h] BYREF
  char v8[24]; // [rsp+30h] [rbp-38h] BYREF

  v2 = *(_QWORD *)(*a1 + 8);
  v8::HandleScope::HandleScope(v8, v2);
  v3 = *(_QWORD *)(*a1 + 40);
  // Value::QuickIsNullOrUndefined  根据AI判断,是指针压缩处理
  if ( (*(_DWORD *)(*a1 + 40) & 3) != 1 // if (!I::HasHeapObjectTag(obj)) return false;
    || *(_WORD *)(*(unsigned int *)(v3 - 1) + (v3 & 0xFFFFFFFF00000000ui64) + 7) != 67
    || (*(_DWORD *)(v3 + 23) & 0xFFFFFFFE) != 10 )
  {
    sub_7FFC1E826F8E(&v7, v2, a1);
    v4 = *a1;
    v5 = v7;
    if ( !v7 )
      v5 = (_QWORD *)(v4 + 16);
    *(_QWORD *)(v4 + 24) = *v5;
  }
  return v8::HandleScope::~HandleScope(v8);
}

其中 (_WORD *)(*(unsigned int *)(v3 - 1) + (v3 & 0xFFFFFFFF00000000ui64) + 7) 执行时崩溃,ida自动暂停;

经检查计算得到的地址实际上指向无效内存区域

第一部分判断:

//  (*(_DWORD *)(*a1 + 40) & 3) != 1
V8_INLINE static bool HasHeapObjectTag(const internal::Address value) {
    return (value & kHeapObjectTagMask/*3*/) == static_cast<Address>(kHeapObjectTag/*1*/);
}

第二部分判断:

// *(_WORD *)(*(unsigned int *)(v3 - 1) + (v3 & 0xFFFFFFFF00000000ui64) + 7) != 67
if (I::GetInstanceType(obj) != I::kOddballType/*67*/) return false;

// (_WORD *)(*(unsigned int *)(v3 - 1) + (v3 & 0xFFFFFFFF00000000ui64) + 7)
// *(unsigned int *)(v3 - 1) + (v3 & 0xFFFFFFFF00000000ui64)
ReadTaggedPointerField(obj, kHeapObjectMapOffset/*0*/)
// xxx + 7
// 开压缩就是8,不开是12
return ReadRawField<uint16_t>(map, kMapInstanceTypeOffset/*8*/); // = map + 7

第三部分判断(感觉不太对,但不重要):

// (*(_DWORD *)(v3 + 23) & 0xFFFFFFFE) != 10 
I::GetOddballKind(obj) == kExternalOneByteRepresentationTag

分析得出,编译开了V8_COMPRESS_POINTERS

实际用nodejs官方版本开了压缩之后还是会崩溃,怀疑是nwjs版本混入了其它东西,暂时没有头绪。。。。。实际上操作不对没开成功。。。

写了一个hello.node,看汇编代码似乎差不多(待仔细比较),能跑,更怪了。。。

2025-10-22 复现

// hello.cc
#include <nan.h>

void Method(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::HandleScope handle_scope(info.GetIsolate());
  auto data = info.NewTarget();
  auto empty = data.IsEmpty();
  auto d = data->IsNullOrUndefined();
  printf("data empty %d nullorundefined %d\n", empty, d);
  info.GetReturnValue().Set(Nan::New("world").ToLocalChecked());
}

void Init(v8::Local<v8::Object> exports) {
  v8::Local<v8::Context> context =
      exports->GetCreationContext().ToLocalChecked();
  auto isolate = exports->GetIsolate();
  exports->Set(context,
               Nan::New("hello").ToLocalChecked(),
               v8::FunctionTemplate::New(isolate, Method)
                   ->GetFunction(context)
                   .ToLocalChecked());
}

NODE_MODULE(hello, Init)

1. 使用nw-gyp构建:nw-gyp rebuild --target=0.54.1

2. 使用vs打开项目

3. 右键项目 -> 属性 -> C/C++ -> 预处理器 -> 预处理器定义 -> 编辑 -> 移除 V8_ENABLE_CHECKS (为了IsNullOrUndefined的内部实现与上面分析一致)

4. 重新构建

使用自己编译的node调用,会崩溃:

const hello = require('D:/github/node-addon-examples/src/1-getting-started/1_hello_world/nan/build/Release/hello.node')

console.log(new hello.hello())

看到这个讨论:https://groups.google.com/g/v8-dev/c/N9BpiGxPaQs/m/Vx9VnEx-BQAJ

取消预处理器定义的继承选项,移除V8_COMPRESS_POINTERS,重新编译测试,程序正常。

疑似之前V8_COMPRESS_POINTERS开启有问题?

2025-10-23

使用VS检查V8_COMPRESS_POINTERS开启的问题,借助IDE高亮提示,判断Flag是否启用。

操作:

1. vcbuild.bat修改set configure_flags="--experimental-enable-pointer-compression" (在这:github issue)

2. common.gypi中'V8_COMPRESS_POINTERS'后追加'V8_ENABLE_SANDBOX', 'V8_COMPRESS_POINTERS_IN_ISOLATE_CAGE'

SANDBOX根据https://groups.google.com/g/v8-users/c/vNlbtTQqs1U
V8_COMPRESS_POINTERS_IN_ISOLATE_CAGE是编译报错,看源代码知道要设置的(好像是这样)

测试程序,正常。


祭夜の咖啡馆 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:[记录] NodeJs调用nwjs模块的分析
喜欢 (0)
[1690127128@qq.com]
分享 (0)
发表我的评论
取消评论
OwO表情
贴图 加粗 删除线 居中 斜体 签到

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

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
(1)个小伙伴在吐槽
  1. 学到了
    yuanyuan2025-10-29 15:23 回复 Windows 10 | Chrome 141.0.0.0