用C++对Duktape JavaScript引擎的简单封装。

Frida源码解析:JavaScript在Native进程中的运行机制与跨语言交互设计 动态插桩是现代软件分析、安全测试和逆向工程中的关键技术,它允许在程序运行时注入并执行自定义代码,实现对目标进程行为的监控与修改。其核心原理在于通过进程注入、API Hook和内存操作等技术,在非JavaScript环境中安全地引入并管理一个脚本运行时。这项技术的价值在于为安全研究人员和开发者提供了强大的动态分析能力,广泛应用于移动应用安全评估、漏洞挖掘、协议分析和自动化测试等场景。以Frida为例,它通过精巧的架构设计,在目标进程内构建了一座连接Native代码与JavaScript的桥梁,其JavaScr 阅读详情

Duktape是款比较小巧的JavaScript引擎,适用于嵌入式系统,不过API使用不太方便,研究了两天决定放弃。下面把测试代码上来,做个备忘吧。

duktape_helper.hpp文件

#ifndef DUKTAPE_HELPER_HPP
#define DUKTAPE_HELPER_HPP

#include <memory>
#include <string>
#include <type_traits>
#include "duktape.h"

namespace duktape {

    class StackAssert {
    private:
        duk_context *m_context;
        unsigned m_expected;
        unsigned m_begin;
    public:
        /**
         * Create the stack checker.
         *
         * No-op if NDEBUG is set.
         *
         * \param ctx the context
         * \param expected the size expected relative to the already existing values
         */
        inline StackAssert(duk_context *ctx, unsigned expected = 0) noexcept
            : m_context(ctx)
            , m_expected(expected)
            , m_begin(static_cast<unsigned>(duk_get_top(ctx)))
        {

        }

        /**
         * Verify the expected size.
         *
         * No-op if NDEBUG is set.
         */
        inline ~StackAssert() noexcept
        {
            if (static_cast<unsigned>(duk_get_top(m_context)) - m_begin != m_expected) {
                std::fprintf(stderr, "Corrupt stack detection in StackAssert:\n");
                std::fprintf(stderr, "  Size at start:            %u\n", m_begin);
                std::fprintf(stderr, "  Size at end:              %d\n", duk_get_top(m_context));
                std::fprintf(stderr, "  Expected (user):          %u\n", m_expected);
                std::fprintf(stderr, "  Expected (adjusted):      %u\n", m_expected + m_begin);
                std::fprintf(stderr, "  Number of stale values:   %u\n", duk_get_top(m_context) - m_begin - m_expected);
                std::abort();
            }
        }
    };

    template< typename T >
    struct duk_result
    {
        static T get(duk_context *ctx, duk_idx_t idx)
        {
            return duk_to_null(ctx,idx);
        }
    };
    template<>
    struct duk_result<int>
    {
        static int get(duk_context *ctx, duk_idx_t idx)
        {
            return duk_to_int(ctx,idx);
        }
    };

    template<>
    struct duk_result<double>
    {
        static double get(duk_context *ctx, duk_idx_t idx)
        {
            return duk_to_number(ctx,idx);
        }
    };

    template<>
    struct duk_result<const char*>
    {
        static const char* get(duk_context *ctx, duk_idx_t idx)
        {
            return duk_to_string(ctx,idx);
        }
    };

    class SharedPtr
    {
        using Deleter = void (*)(duk_context *);
        std::unique_ptr<duk_context,Deleter> ptr_;
        SharedPtr( const SharedPtr &) = delete;
        SharedPtr& operator = ( const SharedPtr&) = delete;
    public:
        SharedPtr(duk_context *p ):ptr_(p,duk_destroy_heap)
        {}
        inline operator duk_context *() noexcept
        {
            return ptr_.get();
        }
        inline operator duk_context *() const noexcept
        {
            return ptr_.get();
        }
    };

    using deleter = void(*)(duk_context*);
    typedef std::unique_ptr<duk_context,deleter> stack_pop;

    class script
    {

    public:
        script():m_ctx(duk_create_heap_default())
        {

        }

        duk_context * context() const
        {
            return m_ctx;
        }
        inline operator duk_context *() noexcept
        {
            return m_ctx;
        }
        inline operator duk_context *() const noexcept
        {
            return m_ctx;
        }

        void evaluate( const std::string & script )
        {
            StackAssert sa(m_ctx);
            stack_pop pop(m_ctx,duk_pop);
            duk_eval_string(m_ctx,script.c_str());
        }

        template<typename R , typename ...Args>
        R evaluate(const char* functionName ,Args ...args )
        {
            StackAssert sa(m_ctx);
            stack_pop pop(m_ctx,duk_pop);
            duk_get_global_string(m_ctx,functionName);
            duk_push_args(m_ctx,args...);
            duk_call(m_ctx,sizeof...(args));

           return duk_result<R>::get(m_ctx,-1);
        }

        void defineFunctions(duk_function_list_entry * fs )
        {
            for( ; fs->key ; fs++ ){
                duk_push_c_function(m_ctx, fs->value, fs->nargs);
                duk_put_global_string(m_ctx, fs->key);
            }
        }
        void defineFunction(const char* key , duk_c_function func, duk_idx_t nargs)
        {
            duk_push_c_function(m_ctx, func, nargs);
            duk_put_global_string(m_ctx, key);
        }

    private:
        SharedPtr m_ctx;
        script( const script &) = delete;
        script& operator = ( const script&) = delete;

    };

    //help template function for duk_push_
    template<typename T> void duk_push_arg(duk_context *ctx,T t) {}
    template<> void duk_push_arg(duk_context *ctx,int t)
    {
        duk_push_int(ctx,t);
    }
    template<> void duk_push_arg(duk_context *ctx,double t)
    {
        duk_push_number(ctx,t);
    }
    template<> void duk_push_arg(duk_context *ctx,const char* t)
    {
        duk_push_string(ctx,t);
    }
    template<> void duk_push_arg(duk_context *ctx,bool t)
    {
        duk_push_boolean(ctx,t);
    }
    template<> void duk_push_arg(duk_context *ctx,void* t)
    {
        duk_push_pointer(ctx,t);
    }
    template <typename ...Args>
    void duk_push_args(duk_context *ctx,Args... args)
    {
        std::initializer_list<int> lst{(duk_push_arg(ctx,std::forward< Args>(args)),0)...};
    }

}//namespace Duktape

#endif // DUKTAPE_HELPER_HPP

main.cpp文件 

#include <iostream>
#include <memory>

#include "duktape_helper.hpp"

static duk_ret_t native_print(duk_context *ctx) {
    duk_push_string(ctx, " ");
    duk_insert(ctx, 0);
    duk_join(ctx, duk_get_top(ctx) - 1);
    std::cout<<duk_safe_to_string(ctx, -1)<<std::endl;
    return 0;
}

static duk_ret_t native_adder(duk_context *ctx) {
    int i;
    int n = duk_get_top(ctx);  /* #args */
    double res = 0.0;

    for (i = 0; i < n; i++) {
        res += duk_to_number(ctx, i);
    }
    duk_push_number(ctx, res);
    return 1;  /* one return value */
}


int main()
{
    std::cout << "Run duktape JavaScript !" << std::endl;

    std::shared_ptr<duktape::script> duk = std::make_shared<duktape::script>();

    duk_function_list_entry functions[] = {
        {"print",native_print,DUK_VARARGS},
        {"adder",native_adder,DUK_VARARGS},
        {0}
    };

    duk->defineFunctions(functions);

    duk->evaluate("var a = 'Hello world'; print(a + ' ' + Duktape.version);");
    duk->evaluate("print('2.2+3.3=' + adder(2.2, 3.3));");
    duk->evaluate("function sum(a,b){ return a+b; }");
    duk->evaluate("var printVersion = function (msg,a,b){"
                  "var disp = msg+(a+b) ; "
                  "print ('Duktape Version: '+ Duktape.version); "
                  "return disp;}");

    const char* result;
    result = duk->evaluate<const char*>("printVersion","call javascript function ",56,44);
    std::cout<<result<<std::endl;
    double ret;
    ret = duk->evaluate<double>("sum",56,44);
    std::cout<<ret<<std::endl;

    return 0;
}

CMakeLists.txt文件 

cmake_minimum_required(VERSION 2.8)

set(CMAKE_VERBOSE_MAKEFILE ON)

project(duk_jse)

set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_C_FLAGS -std=c99)
set(CMAKE_CXX_FLAGS "-std=c++11")

set(LIST_SRC main.cpp
    duktape.c)

add_executable(${PROJECT_NAME} ${LIST_SRC})

代码挺简单,就不注释了。还测试过v7,sipdermonkey1.8,如果是做嵌入式系统v7就够用了,sipdermonkey的api和文档都很好,就是大了些,不过1.8版本编译后也可以。

代码下载

Frida源码解析:从注入指令到JS脚本执行的全链路剖析 动态插桩技术是现代软件安全分析、逆向工程和自动化测试的核心手段,它允许在程序运行时监控和修改其行为。其原理是通过向目标进程注入代码或库,实现对函数调用、内存访问等操作的拦截与处理。这项技术的核心价值在于提供了对闭源软件的深度可观测性和可控性,无需源码即可进行调试、Hook和功能扩展。在移动安全、漏洞挖掘、自动化测试等场景中,动态插桩是分析应用逻辑、绕过安全机制的关键工具。本文以广泛使用的动态插桩框架Frida为例,深入解析其从客户端发起注入指令,到服务端通过ptrace等系统调用将Gadget库注入目标进程 阅读详情

相关推荐

duktape:Duktape-着重于可移植性和紧凑型外观的可嵌入Javascript引擎

杜克塔佩 :warning: Master分支正在针对Duktape 3.x进行不兼容的更改。 要跟踪Duktape 2.x,请遵循v2-maintenance分支。 介绍 是一个可嵌入的Javascript引擎,专注于可移植性和紧凑的。 Duktape易于集成到C / C ++项目中:将duktape.c , duktape.h和duk_config.h到构建中,并使用Duktape API从C代码调用ECMAScript函数,反之亦然。 主要特点: 嵌入式,便携式,紧凑 符合ECMAScript E5 / E5.1,并从ES2015 +更新了一些语义 对ECMAScript 2015(E6)和ECMAScript 2016(E7)的部分支持, , ES2015 TypedArray和Node.js缓冲区绑定 WHATWG编码API的生活标准 内置调试器 内置正则表达式引擎 内置Unicode支持 平台依赖性最小 将引用计数和标记清除垃圾收集与终结处理相结合 协程等自定义功能 使用ECMAScript ES2015代理对象的子集进行属性虚拟化 字节码转储/加载,用于缓存已

1、什么是duktape?

duktape是一个精简的嵌入式JavaScript引擎,可以看做精简版的V8。引擎运行需要的资源少,项目目标是支持集成运行到嵌入式设备上。 公司一个项目,要集成duktape。于是就学习了一下duktap。 我们知道很多基础项目都是C/C++等语言写成的,这样更贴近底层,性能也是最好的。这样的基础项目会提供一些API供上层调用。我们要完成一些项目时,大部分情况都不需要自己造轮子,而是使用别人...

sinat_31066863的博客 1788

Duktape导出全局对象文章代码

Duktape引擎导出全局对象示例代码。

【亲测免费】 Duktape:轻量级嵌入式JavaScript引擎

Duktape 是一个高度可移植且占用空间极小的嵌入式 JavaScript 引擎。它专为需要在资源受限环境中运行的 C/C++ 项目设计,能够轻松集成到现有的代码库中。Duktape 不仅支持 ECMAScript E5/E5.1 标准,还提供了对 ECMAScript 2015+ 的部分支持,使其在现代应用中也能大显身手。 ## 项目技术分析 Duktape 的核心技术优势在于其轻量级和高...

gitblog_00794的博客 816

LLaVA-1.5:多模态视觉问答新突破

LLaVA-1.5在多模态视觉问答(VQA)任务中取得了显著进展,主要得益于视觉-语言连接器的优化和特定任务数据集的增加。通过将连接器升级为两层MLP,模型在处理视觉与语言关系时表现更佳。同时,引入如OKVQA、OCRVQA等数据集,增强了模型在复杂视觉推理任务中的能力。在11个基准测试中,LLaVA-1.5超越了现有方法,展示了其强大的多模态能力。此外,模型通过提升输入图像分辨率、扩展语言模型和改进多语言能力,进一步提升了性能。尽管在短格式回答任务中初期表现不佳,但通过调整提示格式和微调,其性能显著提升

weixin_57060548的博客 945

TS808效果器制作教程

TS808效果器制作教程 可以在立创商城购买到大部分的电阻电容和IC,音频接口,踩钉,电位器和电源接口可以去某宝看看都买得到的。链接https//pan.baidu.com/s/1QId1eIE3fJ2u5NLBSISvGA。安装过程过于繁琐,把所有元器件按照图纸焊接完成就可以调试了,祝你们成功!这是TS808经典效果器制作过程的记录。IC是JRC4558。...

qq_18948149的博客 3427

保姆级linux和单片机上移植duktape

duktape保姆移植

qq_35337506的博客 736

京东技术产品经理面试全记录:从简历投递到一面45分钟实战复盘

本文深度复盘京东技术产品经理面试全流程,从策略准备、思维题拆解、项目阐述到反问谈判,提供了一套可演练的求职策略体系。文章强调该岗位需具备横跨技术与商业的枢纽能力,并通过“QQ分组vs微信标签”等案例,剖析了产品思维与结构化表达在面试中的关键作用,助力候选人将紧张转化为掌控感。

weixin_29275257的博客 630

Duktape:在C/C++项目中嵌入JavaScript

软件可能正在吞噬世界,而JavaScript又可能正在吞噬软件世界。凭借可以嵌入到任何C/C++项目中的、完整兼容ECMAScript 5的引擎,Duktape使得JavaScript超越了浏览器或服务器的界限。\\\Duktape较小的代码库、简单的构建系统,使其非常适合嵌入在其他系统中使用。从技术角度看,它本质上和Lua项目很像,但是它运行的JavaScript却有着更大的生态系统和更多的开发...

cpongo5 656

嵌入式面经篇八——进程&线程

记录一些招聘公司在招聘嵌入式软件岗位时的一些问题,此文为第八篇。进程上文:是指进程由用户态切换到内核态时需要保存用户态时CPU寄存器中的值,进程状态以及堆栈上的内容。即保存当前进程的状态,以便再次执行该进程时,能够恢复切换时的状态,继续执行。进程下文:是指切换到内核态后执行的程序,即进程运行在内核空间的部分。中断上文:硬件通过中断触发信号,导致内核调用中断处理程序,进入内核空间。这个过程中,硬件的一些变量和参数也要传递给内核,内核通过这些参数进行中断处理。

明天你好的博客 1854

ardupilot 获取避障传感器数据

本节主要记录自己学ardupilot的避障代码过程,首先看下怎么注册避障传感器,然后怎么获取避障数据。

陌城烟雨 5524

dukglue: C++与Duktape JavaScript引擎的桥梁

dukglue: C++与Duktape JavaScript引擎的桥梁 项目基础介绍 dukglue是一个开源项目,旨在为Duktape JavaScript引擎提供一个C++的绑定/封装库。通过dukglue,开发者可以在C++程序中嵌入Duktape引擎,并且能够以类型安全的方式将C++函数和对象暴露给JavaScript脚本,使得C++和JavaScript之间的交互变得简单而直接。该项目...

gitblog_00670的博客 391

【k8s故障处理篇】calico-node启动失败“Felix is not live: Get “http://localhost:9099/liveness” 解决办法(V1.30.3版本)

【k8s故障处理篇】calico-node启动失败“Felix is not live: Get “http://localhost:9099/liveness” 解决办法(V1.30.3版本)

jks212454的博客 1091

什么是duktape

duktape是一个精简的嵌入式JavaScript引擎,可以看做精简版的V8。引擎运行需要的资源少,项目目标是支持集成运行到嵌入式设备上。 公司一个项目,要集成duktape。于是就学习了一下duktap。 我们知道很多基础项目都是C/C++等语言写成的,这样更贴近底层,性能也是最好的。这样的基础项目会提供一些API供上层调用。我们要完成一些项目时,大部分情况都不需要自己造轮子,而是使用别人的轮子,我们只需要编写上层业务逻辑将这些轮子组合集成起来就可以了,并且很多时候,上层业务逻辑经常改动。需要更灵活

whl0071的专栏 1230

海思Hi3519A开发:DSP开发指南

通过创建DSP项目、实现算法、编译调试等步骤,开发者可以充分利用Hi3519A芯片集成的DSP,实现各种音视频处理功能。通过以上示例,我们可以看到在Hi3519A开发平台上进行DSP开发是一项强大而灵活的任务。在调试过程中,可以使用调试工具提供的功能,如断点设置、变量查看等,以便更好地理解和优化DSP算法的执行过程。在Hi3519A开发平台上,我们可以利用DSP的高性能计算能力来加速这些算法的执行。在实际的DSP开发中,算法的实现可能更加复杂,需要结合具体的项目需求进行。3.2 DSP算法实现。

QoTypescript的博客 1496

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Duktape 2.7.0 C++ 异常模式解析:用 DUK_USE_CPP_EXCEPTIONS 取代 setjmp/longjmp 实现安全的长控制转移

Duktape 默认使用 `setjmp()` / `longjmp()` 实现内部的长控制转移(long control transfers,即从 JS 执行栈深处直接跳转到错误处理点),这会导致 C++ 程序中最关键的保障失效:**Duktape/C 函数栈上的自动对象析构函数不会被调用**,基于 RAII(Resource Acquisition Is Initialization,资源获取

gitblog_01109的博客 299

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Conky 系统监控完全指南:从安装到 Lua 配置扩展一步到位

Conky 是一款轻量级系统监控工具,能把 CPU、内存、网络、磁盘等实时数据直接渲染到桌面,也可以把数据输出到控制台、文件或 HTTP 接口。它支持 X Window 与 Wayland 等图形环境,内置 300 多种监控对象,配置文件用 Lua 语法编写,方便按需扩展。对只想看资源占用的人,几分钟就能上手;对想深度定制的人,Lua 提供了很大的扩展空间。 - 资源占用低,适合常驻桌面 - 覆

gitblog_00099的博客 934

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Duktape模块系统:CommonJS加载器的实现原理

Duktape作为一款轻量级、可嵌入的JavaScript引擎,其模块系统基于CommonJS规范实现,为嵌入式环境提供了简洁高效的代码组织方案。本文将深入解析Duktape模块加载器的核心机制和工作原理。 ## 🔍 Duktape模块系统概述 Duktape的模块系统遵循CommonJS Modules/1.1.1规范,通过全局的`require()`函数实现模块的加载和管理。与Node.

gitblog_00809的博客 708

Duktape 2.7.0 Extras 完全指南:Duktape 官方扩展模块的集成与实战(含 Karabiner-Elements 源码实例)

Duktape 是一个体积小巧、可嵌入的 ECMAScript(JavaScript)引擎,其官方发行版在 [vendor/duktape-2.7.0/extras](https://link.gitcode.com/i/4b8a2980562c380d31c05f54415c6f7a) 目录下附带了一套名为 **Extras(扩展模块与工具)** 的附加组件。本文以该目录的 [README.rs

gitblog_00120的博客 714

5 步装好 Steam Deck 插件加载器:Decky Loader 安装教程与插件商店指南

Decky Loader 是一款免费开源的 Steam Deck 插件加载器,装上它,掌机就能加载社区开发的第三方插件——换菜单样式、看实时性能、录屏、替换音效,都从这里开始。 ## 装完它能干什么 | 你的场景 | 装好插件后的效果 | | --- | --- | | 默认菜单看腻了 | 按自己的喜好改样式、配色和布局 | | 想知道画面为什么卡 | 帧率、CPU、GPU 占用直接摆在眼前

gitblog_00949的博客 714

Karabiner-Elements 内嵌 Duktape 2.7.0:print-alert 扩展模块的移植与使用指南

本文聚焦于 Karabiner-Elements 仓库中随附的 Duktape 2.7.0 引擎的 `print-alert` 扩展模块(位于 [vendor/duktape-2.7.0/extras/print-alert](https://link.gitcode.com/i/9cec8367c0c2ea975c099f17b1760858)),讲解如何在 Duktape 2.x 中恢复 Du

gitblog_00447的博客 334

使用 Duktape 实现 8 位字符编码到 CESU-8 的运行时转换:codepage-conv 示例深度解析

在嵌入式脚本引擎场景中,经常需要处理非 UTF-8 编码的输入数据。本篇文章以 Karabiner-Elements 仓库内捆绑的 Duktape 2.7.0 源码树中的 `codepage-conv` 示例为核心,深入讲解如何在完全不依赖 iconv 等外部库的前提下,将 ISO-8859-1、Windows-1252 等 8 位单字节编码的字符串转换为 Duktape 内部使用的 CESU-8

gitblog_00176的博客 926

supercookie 实战指南:用 favicon 缓存实现浏览器指纹追踪

supercookie 是一个演示项目:它利用浏览器的 favicon 缓存(F-Cache)给访问者分配一个几乎无法清除的唯一 ID,实现不依赖 cookie 的浏览器指纹追踪。用户清 cookie、删缓存、开无痕模式甚至重启系统之后,服务器依然能通过"你这次向哪些子路径要了图标、哪些没要"认出是同一个人。下文先拆原理,再走完整流程,最后给出 Docker 部署方法和防御思路。 ## 🧩 它

gitblog_00637的博客 435

Karabiner-Elements 中的 Duktape 调试传输实现:基于 debug-trans-dvalue 的本地调试协议编解码指南

本文围绕 Duktape 官方示例 `debug-trans-dvalue`(位于本仓库 `vendor/duktape-2.7.0/examples/debug-trans-dvalue/`)展开,剖析一套将 Duktape 调试协议在本地完成解码/编码的调试传输(debug transport)实现。该示例把协议字节流抽象为易于在 C 语言中处理的 "dvalue" 结构,并通过回调把完整的握

gitblog_00904的博客 1008

使用 WebAssembly 打造定制 JS Runtime

本文为来自 教育-成人与创新-前端团队 成员的文章,已授权 ELab 发布。背景这是一次简短的整活与折腾,起因是在 lightdm-webkit2-greeter 这个 lightdm 插件中看到了自定义 JS Runtime的魔力,它支持在显示管理器中使用 web 技术去自定义登录界面,与操作系统的交互是通过 Runtime 中的一组 JS API来实现登录、关机、睡眠等功能。https://d...

奇舞周刊 343
上一篇: Macos 编译SpiderMonkey1.8
firebolt2002
博客等级 码龄24年 74粉丝 21原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值