1.husky 源码浅析
2.Pytorch hook 与 dataparallel 使用—— deoldify 源码解析 part1
3.使用 Gitea + Git Hook 实现 Hexo 博客源码托管与持续集成
4.详解Hook框架frida,硬盘源码让你在逆向工作中效率成倍提升
5.沙盒源代码防泄密的硬盘源码 HOOK 策略是如何设定的?
6.这些hook更优雅的管理你的状态
husky 源码浅析
解析 Husky 源码:揭示 Git 钩子的奥秘
前言
在探索 Husky 的工作原理之前,让我们先回顾一下自定义 Git Hook 的硬盘源码概念。通过 Husky,硬盘源码我们能够实现对 Git 钩子的硬盘源码指定目录控制,灵活地执行预先定义的硬盘源码片头素材源码命令。本篇文章将带领大家深入 Husky 的硬盘源码源码,揭示其工作流程和使用 Node.js 编写 CLI 工具的硬盘源码要点。Husky 工作流程
从 Husky 的硬盘源码安装流程入手,我们能够直观地理解其工作原理。硬盘源码主要步骤如下:执行 `npx husky install`。硬盘源码
通过 Git 命令,硬盘源码将 hooks 目录指向 Husky 提供的硬盘源码目录。
确保新拉取的硬盘源码仓库在执行 `install` 后自动调整 Git hook 目录,以保持一致性。硬盘源码
在这一过程中,Husky 通过巧妙地添加 npm 钩子,确保了新仓库在安装完成后能够自动配置 Git 钩子路径,实现了跨平台的统一性。源码浅析
bin.ts
bin.ts 文件简洁明了,核心在于模块导入语法和 Node.js CLI 工具的实现。它支持了导入模块的两种方式,并解释了在 TypeScript 中如何灵活使用它们。npm 中的可执行文件
通过配置 package.json 的 `bin` 字段,我们可以将任意脚本或工具作为 CLI 工具进行全局安装,以便在命令行中直接调用。Husky 利用这一特性,为用户提供了一个简洁的安装流程和便捷的调用方式。获取命令行参数
在 Node.js 中,`process.argv` 提供了获取命令行参数的便捷方式。通过解析这个数组,我们可以轻松获取用户传递的参数,实现命令与功能的对应。index.ts
核心逻辑在于安装、配置和卸载 Git 钩子的函数。Husky 的代码结构清晰,易于理解。其中,`core.hooksPath` 的配置和权限设置(如 `mode 0o`)是关键步骤,确保了 Git 钩子的执行权限和统一性。husky.sh
作为初始化脚本,husky.sh 执行了一系列环境配置和日志输出操作。其重点在于根据不同 Shell 环境(如 Zsh)进行适配性处理,确保 Husky 在各类环境中都能稳定运行。结语
Husky 的实现通过 `git config core.hooksPath` 和 `npm prepare` 钩子的巧妙结合,不仅简化了 Git 钩子的配置流程,还提升了代码的可移植性和一致性。使用 Husky,开发者能够更灵活地管理 Git 钩子,提升项目的杭州棋牌源码交易自动化程度。Pytorch hook 与 dataparallel 使用—— deoldify 源码解析 part1
在调整项目deoldify从单GPU到多GPU训练时,遭遇了一系列问题,促使我对PyTorch的理解进一步加深。项目中的Unet结构在上采样过程中使用了skip connection,通常做法是硬编码实现,这种方式简洁明了,但若需要改变网络结构,如从resnet调整为resnet,这样的硬编码方式显然不够灵活。
deoldify采取了另一种方法,在需要保存输出的网络层中插入自定义的hook函数,并利用PyTorch的register_forward_hook接口,确保每次前向传播时都能触发该函数,从而保存输出以供后续使用。自定义hook的核心代码展示了这一过程。
在单GPU训练中,上述方法运行正常,然而在多GPU环境下,遇到了hook存储的值与concat操作的权重不在同一GPU设备上的问题,引发错误。起初,我误以为nn.DataParallel会自动处理这个问题,但事实并非如此,我开始了深入的debug之旅。
首先,成功复现了错误现象,发现存储在hook中的值分布不均,部分在GPU1上,其他在GPU0上。这表明nn.DataParallel并没有将hook备份并分发到每个GPU上,而是多个GPU共享同一个Hooks类及接口。进一步检查发现,不同线程对应的hook接口及存储值的内存地址相同,这证实了hook并不适用于多GPU运行环境。
为解决这一问题,参考了相关文献,并将hook接口进行了修改,引入当前线程ID作为键,值对应输出,从而实现了线程安全。这一调整使得程序在第一个迭代周期正常运行。值得注意的是,第二个迭代周期又出现了问题,但这与hook的多线程运行无关,详情请见后续文章。
在debug过程中,为了简化操作,插入打印信息来观察多线程运行情况。然而,.net+考试+源码在获取hook中多线程运行信息时,遇到了异常,因获取`self.stored[key]`时报出`dict找不到key`的错误,这是因为多线程在写入`hook.stored`时,for循环期间警告`self.stored`的大小发生变化,这表明发生了并发错误,部分值并未正确写入。最终,删除了打印代码,程序恢复正常运行。
本次经历不仅解决了多GPU环境下hook使用的问题,也加深了我对PyTorch多GPU运行机制的理解,特别是关于线程安全和并发操作的注意事项。
使用 Gitea + Git Hook 实现 Hexo 博客源码托管与持续集成
本文将介绍如何在2核4G的阿里云ECS上,利用Gitea和Git Hook来搭建Hexo博客的源码托管与持续集成。Gitea作为轻量级的开源Git服务,替代了性能占用较大的GitLab,以降低服务器负担。 在开始之前,确保你具备以下基础:熟悉此前文章中的相关知识
1. 安装与配置
1.1 安装前置依赖
1.2 创建工作用户
1.3 下载并设置Gitea权限
1.4 初始化Gitea服务
1.5 配置Nginx反向代理
1.6 为数据安全添加Nginx登录验证
1.7 导入本地仓库
2. 安装Node.js与Hexo
2.1 安装Node.js和创建软链接
2.2 安装Hexo并创建可执行脚本
3. 创建Hexo仓库与Git Hook
3.1 创建仓库并配置忽略文件
3.2 配置Git Hook脚本
总结
通过这些步骤,你实现了Hexo博客源码的自动管理和远程部署,本地专注于创作,线上自动构建。在实践过程中,记得根据服务器安全策略限制对端口的访问,以确保整体安全。详解Hook框架frida,让你在逆向工作中效率成倍提升
详解Hook框架frida,让你在逆向工作中效率成倍提升
一、frida简介
frida是一款基于python + javascript的hook框架,支持运行在各种平台如android、ios、linux、win、osx等。主要通过动态二进制插桩技术实现代码注入,收集运行时信息。
插桩技术分为两种:源代码插桩和二进制插桩。源代码插桩是将额外代码注入到程序源代码中;二进制插桩则是将额外代码注入到二进制可执行文件中。其中,静态二进制插桩在程序执行前插入额外代码和数据,生成永久改变的可执行文件;动态二进制插桩则在程序运行时实时插入额外代码和数据,对可执行文件无永久改变。
二、frida的安装
frida框架包括frida CLI和frida-server两部分。frida CLI是用于系统交互的工具,frida-server则用于目标机器上的代码注入。
1. frida CLI安装要求包括系统环境(Windows、macOS、投票系统+asp源码GNU/Linux)、Python(最新3.x版本)等。通过pip安装frida CLI,frida CLI是frida的主要交互工具。
2. 分别下载frida-server文件(格式为frida-server-(version)-(platform)-(cpu).xz),并根据设备类型选择对应的版本。下载文件后解压,将frida-server文件推送到Android设备,添加执行权限并运行(需要root权限)。
3. frida还提供了其他工具,如frida-ps用于列出进程,frida-trace、frida-discover、frida-ls-devices、frida-kill等。这些工具用于不同场景,具体使用可参考frida官网。
三、frida Hook实战
通过制作类似微信抢红包的插件来演示frida的使用。首先拦截微信信息持久化到本地的接口(com.tencent.wcdb.database.SQLiteDatabase的insert()方法),解析获取每条信息的内容、发送者等信息。
抢红包流程分析:点击打开红包时,执行请求(ad类)发送抢红包的请求。需要的参数包括头像、昵称、发送者信息等,参数主要来自luckyMoneyReceiveUI.kRG类。通过解析解析参数,发送com.tencent.mm.plugin.luckymoney.b.ag类请求,并获取timingIdentifier,最后发送com.tencent.mm.plugin.luckymoney.b.ad类请求即可抢到红包。
四、模拟请求
分析微信的请求发送方法,通过frida实现请求发送。主要通过反射获取发送请求的Network,然后调用其a方法发送请求。解析红包信息,发送ag请求并获取timingIdentifier,改造SQL的insert方法,实现抢红包插件。
附录
实验环境包括微信版本6.6.7、frida版本.0.、frida-server版本、Android版本7.0等。ISEC实验室作为网络安全服务提供商,专注于网络安全技术研究,提供全面的网络安全服务和解决方案。
沙盒源代码防泄密的配送员系统+源码 HOOK 策略是如何设定的?
沙盒源代码防泄密的 HOOK 策略是通过进程偏转安全策略来实现的。在沙盒模式下,区分涉密/非涉密进程,依据进程涉密性质设定沙箱偏转安全策略。对磁盘目录进行修改(非加密),防止其中涉密文件被进程非法访问,只有合规进程方可访问涉密文件 。
这些hook更优雅的管理你的状态
本文是深入浅出ahooks源码系列文章的第十二篇,这个系列的目标主要有以下几点:加深对Reacthooks的理解。
学习如何抽象自定义hooks。构建属于自己的Reacthooks工具库。
培养阅读学习源码的习惯,工具库是一个对源码阅读不错的选择。
今天我们来聊聊ahooks中那些可以帮助我们更优雅管理我们state(状态)的那些hook。一些比较特殊的,比如cookie/localStorage/sessionStorage,useUrlState等,我们已经单独拿出来细讲了,感兴趣可以看看笔者的历史文章。
useSetState管理object类型state的Hooks,用法与class组件的this.setState基本一致。
先来了解一下可变数据和不可变数据的含义和区别如下:
可变数据(mutable)即一个数据被创建之后,可以随时进行修改,修改之后会影响到原值。
不可变数据(Immutable)就是一旦创建,就不能再被更改的数据。对Immutable对象的任何修改或添加删除操作都会返回一个新的Immutable对象。
我们知道,ReactFunctionComponents中的State是不可变数据。所以我们经常需要写类似如下的代码:
setObj((prev)=>({ ...prev,name:'Gopal',others:{ ...prev.others,age:'',}}));通过useSetState,可以省去对象扩展运算符操作这个步骤,即:
setObj((prev)=>({ name:'Gopal',others:{ age:'',}}));其内部实现也比较简单,如下所示:
调用设置值方法的时候,会根据传入的值是否为函数。如果是函数,则入参为旧状态,输出新的状态。否则直接作为新状态。这个符合setState的使用方法。
使用对象拓展运算符,返回新的对象,保证原有数据不可变。
constuseSetState=<SextendsRecord<string,any>>(initialState:S|(()=>S),):[S,SetState<S>]=>{ const[state,setState]=useState<S>(initialState);//合并操作,并返回一个全新的值constsetMergeState=useCallback((patch)=>{ setState((prevState)=>{ //新状态constnewState=isFunction(patch)?patch(prevState):patch;//也可以通过类似Object.assign的方式合并//对象拓展运算符,返回新的对象,保证原有数据不可变returnnewState?{ ...prevState,...newState}:prevState;});},[]);return[state,setMergeState];};可以看到,其实就是将对象拓展运算符的操作封装到内部。
还有其他更优雅的方式?我们可以使用use-immer
useImmer(initialState)非常类似于useState。该函数返回一个元组,元组的第一个值是当前状态,第二个是updater函数,它接受一个immerproducer函数或一个值作为参数。
使用如下:
const[person,updatePerson]=useImmer({ name:"Michel",age:});functionupdateName(name){ updatePerson(draft=>{ draft.name=name;});}functionbecomeOlder(){ updatePerson(draft=>{ draft.age++;});}当向更新函数传递一个函数的时候,draft参数可以自由地改变,直到producer函数结束,所做的改变将是不可变的,并成为下一个状态。这更符合我们的使用习惯,可以通过draft.xx.yy的方式更新我们对象的值。
useBoolean和useToggle这两个都是特殊情况下的值管理。
useBoolean,优雅的管理boolean状态的Hook。
useToggle,用于在两个状态值间切换的Hook。
实际上,useBoolean又是useToggle的一个特殊使用场景。
先看useToggle。
这里使用了typescript函数重载声明入参和出参类型,根据不同的入参会返回不同的结果。比如第一个入参为boolean布尔值,则返回一个元组,第一项为boolean值,第二个为更新函数。优先级从上到下依次变低。
入参可能有两个值,第一个为默认值(认为是左值),第二个是取反之后的值(认为是右值),可以不传,不传的时候,则直接根据默认值取反!defaultValue。
toggle函数。切换值,也就是上面的左值和右值的转换。
set。直接设置值。
setLeft。设置默认值(左值)。
setRight。如果传入了reverseValue,则设置为reverseValue。否则设置为defautValue的取反值。
//TS函数重载的使用functionuseToggle<T=boolean>():[boolean,Actions<T>];functionuseToggle<T>(defaultValue:T):[T,Actions<T>];functionuseToggle<T,U>(defaultValue:T,reverseValue:U):[T|U,Actions<T|U>];functionuseToggle<D,R>(//默认值defaultValue:D=falseasunknownasD,//取反reverseValue?:R,){ const[state,setState]=useState<D|R>(defaultValue);constactions=useMemo(()=>{ constreverseValueOrigin=(reverseValue===undefined?!defaultValue:reverseValue)asD|R;//切换stateconsttoggle=()=>setState((s)=>(s===defaultValue?reverseValueOrigin:defaultValue));//修改stateconstset=(value:D|R)=>setState(value);//设置为defaultValueconstsetLeft=()=>setState(defaultValue);//如果传入了reverseValue,则设置为reverseValue。否则设置为defautValue的反值constsetRight=()=>setState(reverseValueOrigin);return{ toggle,set,setLeft,setRight,};//useToggleignorevaluechange//},[defaultValue,reverseValue]);},[]);return[state,actions];}而useBoolean是对useToggle的一个使用。如下,比较简单,不细说
exportdefaultfunctionuseBoolean(defaultValue=false):[boolean,Actions]{ const[state,{ toggle,set}]=useToggle(defaultValue);constactions:Actions=useMemo(()=>{ constsetTrue=()=>set(true);constsetFalse=()=>set(false);return{ toggle,set:(v)=>set(!!v),setTrue,setFalse,};},[]);return[state,actions];}usePrevious保存上一次状态的Hook。
其原理,是每次状态变更的时候,比较值有没有发生变化,变更状态:
维护两个状态prevRef(保存上一次的状态)和curRef(保存当前状态)。
状态变更的时候,使用shouldUpdate判断是否发生变化,默认通过Object.is判断。开发者可以自定义shouldUpdate函数,并决定什么时候记录上一次状态。
状态发生变化,更新prevRef的值为上一个curRef,并更新curRef为当前的状态。
constdefaultShouldUpdate=<T>(a?:T,b?:T)=>!Object.is(a,b);functionusePrevious<T>(state:T,shouldUpdate:ShouldUpdateFunc<T>=defaultShouldUpdate,):T|undefined{ //使用了useRef的特性,一直保持引用不变//保存上一次值constprevRef=useRef<T>();//当前值constcurRef=useRef<T>();//自定义是否更新上一次的值if(shouldUpdate(curRef.current,state)){ prevRef.current=curRef.current;curRef.current=state;}returnprevRef.current;}useRafState只在requestAnimationFramecallback时更新state,一般用于性能优化。
window.requestAnimationFrame()告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。
假如你的操作是比较频繁的,就可以通过这个hook进行性能优化。
重点看setRafState方法,它执行的时候,会取消上一次的setRafState操作。重新通过requestAnimationFrame去控制setState的执行时机。
另外在页面卸载的时候,会直接取消操作,避免内存泄露。
functionuseRafState<S>(initialState?:S|(()=>S)){ constref=useRef(0);const[state,setState]=useState(initialState);constsetRafState=useCallback((value:S|((prevState:S)=>S))=>{ cancelAnimationFrame(ref.current);ref.current=requestAnimationFrame(()=>{ setState(value);});},[]);//unMount的时候,去除监听useUnmount(()=>{ cancelAnimationFrame(ref.current);});return[state,setRafState]asconst;}useSafeState用法与React.useState完全一样,但是在组件卸载后异步回调内的setState不再执行,避免因组件卸载后更新状态而导致的内存泄漏。
代码如下:
在更新的时候,通过useUnmountedRef判断如果组件卸载,则停止更新。
functionuseSafeState<S>(initialState?:S|(()=>S)){ //判断是否卸载constunmountedRef=useUnmountedRef();const[state,setState]=useState(initialState);constsetCurrentState=useCallback((currentState)=>{ //如果组件卸载,则停止更新if(unmountedRef.current)return;setState(currentState);},[]);return[state,setCurrentState]asconst;}useUnmountedRef这个我们之前提过,简单回顾下,其实就是在hook的返回值中标记组件为已卸载。
constuseUnmountedRef=()=>{ constunmountedRef=useRef(false);useEffect(()=>{ unmountedRef.current=false;//如果已经卸载,则会执行return中的逻辑return()=>{ unmountedRef.current=true;};},[]);returnunmountedRef;};useGetState给React.useState增加了一个getter方法,以获取当前最新值。
其实现如下:
其实就是通过useRef记录最新的state的值,并暴露一个getState方法获取到最新的。
setObj((prev)=>({ name:'Gopal',others:{ age:'',}}));0这在某一些情况下,可以避免React的闭包陷阱。如官网例子:
setObj((prev)=>({ name:'Gopal',others:{ age:'',}}));1假如这里不使用getCount(),而是直接使用count,是获取不到最新的值的。
总结与思考React的functionComponent的状态管理还是比较灵活,我们可以针对一些场景进行封装和优化,从而更优雅的管理我们的state状态,希望ahooks这些封装能对你有所帮助。
原文:/post/纪念我HooK逝世的青春--XIgnCode3.TP.NP.HS.PP.GPK
HooK技术,从应用层到内核层,各种技术阶段的HOOK,我自学以来,对它有了深入的了解,也运用它解决了许多问题。在过去的两年多里,我利用HOOK机制绕过各种内核保护,这已经成为我技能中的一部分。感谢各位大佬的支持与帮助。
我将代码存放在硬盘上,希望能在不久的将来发布出来,避免让它们发霉。虽然我不擅长表达,但如果有说错的地方,欢迎大家指正。通过代码,我实现了一些功能,虽然还有改进空间,但已经能过滤掉部分保护。
针对Windows 7x位系统,我开发了DisablePG.c,用于绕过PG检查,需要调整偏移量。PtotectTools.c实现了一种保护某进程或窗口的方法,使用HOOK技术。SsdtHook.c则实现了调试权限位移、双机调试等功能,还去除了各种不必要的模块操作。
我还创建了注册文件回调、去除线程进程模块回调、调试端口、IO、保护进程断链、注册表回调、进程回调处理、PG和保护进程窗体等功能。请注意,这些只是源代码的一部分,具体实现还需要查看项目文件。如果有任何不准确的地方,欢迎各位大佬指正。
我分享的仅仅是一套源代码,请在虚拟机上测试,以避免给您造成任何损失。请勿用于非法用途,我对此不负任何责任。我正在寻找内核/安全开发领域的工作,无论地区和公司类型。我目前的学历为中专,正在报考大专课程。文件较大,无法上传到论坛,但您可以访问以下链接获取:share.weiyun.com/5bYpM2...
本文由看雪论坛 sorrywyb 原创,如需转载,请注明来自看雪社区。请关注看雪学院公众号ikanxue,获取更多干货信息。
注入挂hook是什么
注入挂hook是一种在程序运行时动态修改其行为的技术。
注入挂hook的基本原理是通过向目标程序中注入特定的代码,来改变或扩展程序原有的功能。这种技术通常用于调试、性能分析或者实现某些特殊功能,但也可能被恶意软件用于非法目的。在计算机安全领域,注入挂hook有时被用于分析恶意软件的行为或者进行安全研究。
具体来说,注入挂hook涉及到几个关键步骤。首先,需要确定目标程序的进程,并了解其内部结构和运行机制。接着,通过特定的方法将自定义的代码注入到目标进程中。这些注入的代码可以是一段钩子函数,用于拦截并修改原程序的某些函数调用或系统调用。例如,一个安全研究人员可能会注入一个钩子来监控恶意软件的网络通信,从而分析其行为模式。
在实际应用中,注入挂hook技术有着广泛的用途。在软件开发和测试阶段,开发人员可以利用这一技术来调试程序,监控关键函数的调用情况,或者测试程序在不同条件下的反应。在安全领域,研究人员经常使用注入挂hook来分析恶意软件如何与远程服务器通信,或者监控其对系统资源的访问情况。然而,这项技术也可能被用于非法活动,如制作恶意软件或进行网络攻击,因此需要谨慎使用,并确保遵守法律法规。
总的来说,注入挂hook是一种强大的技术,能够在不修改原程序源代码的情况下,动态地改变程序行为。它既可以用于合法的软件开发和安全研究,也可能被滥用于非法活动。因此,掌握这项技术的人员需要具备良好的道德素质和法律意识。
VirtualAPP源码解析-Native Hook技术
Native Hook技术在VirtualAPP中的应用背景在于虚拟APP的文件访问重定向。VirtualAPP作为子进程启动一个虚拟APP时,文件存储路径会默认指向VirtaulAPP的data目录。这可能导致文件访问冲突,且无法实现APP间的隔离。VirtualAPP通过Native Hook技术解决了这个问题,让每个APP有独立的文件存储路径。
实现原理关键在于VClientImpl的startIOUniformer方法,通过进行存储路径映射,将子进程访问的目录路径转换为虚拟app路径。这个过程通过调用IOUniformer.cpp的startUniformer方法实现。我们知道Android系统基于Linux内核,文件读写操作通过库函数进行系统调用。因此,Native Hook技术实现方式是替换libc库函数的方法,将输入参数替换为虚拟app路径,从而实现文件访问路径的重定向。
要确定需要hook的函数,开发者需要查看libc源码。Native Hook技术有PLT Hook与Inline Hook两种实现方式。PLT Hook主要通过替换程序链接表中的地址,而Inline Hook则直接修改汇编代码,实现更广泛的场景与更强的能力。虚拟app使用的第三方开源项目Cydia Substrate实现了Inline Hook方案,而爱奇艺开源的xHook则采用了PLT Hook方案。虚拟app通过宏定义灵活运用这两种Hook方案,实现对libc库函数的替换。
Native Hook技术的实现过程涉及到so动态链接、ELF文件格式、汇编指令等知识,其具体步骤包括定义Hook调用和替换方法。例如,通过HOOK_SYMBOL宏定义函数指针,HOOK_DEF宏定义替换函数,最终通过hook_function方法实现Hook操作。MSHookFunction函数即为Cydia Substrate提供的Hook能力。
学习Native Hook技术需要逐步积累,理解其原理和实现过程需要时间和实践。后续文章将深入探讨MSHookFunction的具体实现原理,进一步帮助读者掌握Native Hook技术。