写PC微信辅助感悟1

最近只要有空就写PC辅助功能,今天一天基本完成发送图片,发送文件,添加好友(包括单向和群好友之类的hook点),成就感还是蛮高的,于是记录一下最近心得。

1:辅助本质:找函数和找数据

2:找函数,对于网络程序,一般是投递网络事件这个点,以前是send这个点,但是现在如果同步发送网络请求程序,估计都很low。如果tx写这么low b程序的话估计会被喷死,所以一般都是一个通用的网络库(肯定是异步与ui主线程分开),所以一定有一个通用的投递网络请求地方,微信就有一个,因为微信他们有打日志习惯。

SceneCenter::doScene 微信给这个函数起这个名字,所以后面写功能都会这个函数打断点然后就通过堆栈回溯,找到合适的hook点。

3: 一般windows 程序都是有事件循环,我们自己开发时候,总会有个mainwnd(微信就有一个,我们自己开发也差不多,无论你用mfc还是别的,微信用的duilib),如果找到这个合适点,那么很多功能就好写了,找到起点,这个点就是一个很好的hook点,因为我们开发程序,也喜欢这么写,一个大的事件循环,那所有的功能,统一通过事件来做,微信也差不多这么样子,这个也是最近我才想到这一点,一下子就加快功能开发,因为Hook点查找,要找到合适,就是要找到容易构建参数的地方,最好不要太多对象,不然我们要找到对象指针是从哪里传递的,又要分析好久,如果是全局对象,那么还好说,如果是局部变量,你又去找合适函数,怎么构建。那么这样递归下去,就搞的非常难搞了,所以找到主要事件循环起点,那个点一般参数都比较简单,就是常见的类型,一般不是对象,也有对象的存在。

4:根据第三种,那么事件循环,一般是一个窗口类,那么肯定有对应的ecx 指针对象,那么肯定这个不是全局变量,或者不是那么好找,我们怎么获取呢,事件循环,那么一定很频繁调用,我们只要在事件函数找一个点hook,获取ecx就可以了,然后保存在自己地方,那么就简单了。

5:数据查找,这个我目前没有找到非常方便方法,只能根据数据关系,慢慢查找。

总结:

其实写辅助,更加要求对程序开发能力,你这样子才能想出他们代码大概是怎么写的,所以程序员的基本功要牢。

http://www.xiaoyutang.net/wordpress/wp-admin/post-new.php

 

 

补充:

函数调用压入堆栈,不是每个都会用掉,可以调用时候,修改成0x0进行判断验证(前提通过代码分析是否有访问,然后再去验证)

PC 微信删除群里面好友分析记录

背景:

花2天时间弄出来了,花了2天分析,怎么构建参数。找到函数位置比较顺利,但是构建参数,总是崩溃。这个就比较蛋疼了,做这个辅助软件,最怕就是参数够着,比找数据结构还恶心一点,所以我简单记录一下,等过一段时间再更新一下,上图片,现在用的家里的PC电脑,笔记本忘记带充电线,没法重新过一遍流程,只是把思路记录一下而已。

过程:

一般我们要找到合适的函数,我们需要通过特征值,找到有关的函数,然后回溯。所以最好找到底,否者你回溯没有任何意义,反过来找容易很多,顺着找分支过多,很那区分哪个是有用的。所以我一般希望回溯,通过堆栈参数,进行分析。然后尽可能找到好构建参数地点。

因为我前面做一些微信的辅助功能,所以找出所有cgi-bin字符串,通过英文找到有关删除群好友,然后就很顺利找到一个合适构建点,这个点肯定是参数什么群,删除什么人。所以我只要构建参数,我开始简单构建这2个参数,但发现堆栈破坏,明显构建参数不对,但找了半天没有找出来。后面想一定函数访问别的参数,所以跟函数里面,一个一个看,看他到底访问哪些地址,果然有几个地方,我没有构建对,导致访问野地址,导致崩溃了。。。。

待续。。。。。。。。。。。

 

 

c语言例子—-替换call的地址(call相对地址算法)

背景:

为了熟悉写某个需要替换调用call的代码,但不是hook call。比喻 0x12345678  call 0x1111111。比喻我们替换call 0x11111111调用我们自己的函数,比喻替换成call 0x22222222 ,这样的做的好处,我们只是替换某处逻辑,不用改变0x11111111的逻辑。如果没有明白直接见我的代码例子

 

#include “stdafx.h”
#include <windows.h>
#include <mmsystem.h>
#include <stdio.h>
void main(void);
void testRealFunc1(){
printf(“函数1:%x”, testRealFunc1);
}
void testRealFunc2(){
printf(“函数2:%x”, testRealFunc2);
}
void hooktestCall(){
void *p = testRealFunc2;
int testRealFunc2Addr = (int)(p);
//memcpy(&testRealFunc2Addr,(void*)((int)testRealFunc2Addr+1),4);//这才真正的地址,函数名不是真正地址
int moudleAddr = (int)GetModuleHandleW(NULL);
int offset = (0x0F416BE-0xf30000);//调试的计算出来,可以同OD,或者直接VS反汇编查看得出来
int hookAddr =  moudleAddr + offset;
//构造code
unsigned char hookContext[] = {232,0,0,0,0};
//内存地址不对啊
//所以的还得计算
//机器码E8后面所跟的32位数=目标地址-下条指令的地址
//机器码E8后面所跟的32位数=testRealFunc2Addr-(hookAddr+0x5)
int rTestRealFunc2Addr = testRealFunc2Addr – (hookAddr+0x5);
memcpy(hookContext+1,&rTestRealFunc2Addr, 4);//call 0x111 是相对地址,必须要公司转换,还不与mov eax,call eax 做转换,反正都是5个字节
try{
DWORD dwOldCode = 0;
if(VirtualProtect((void*)hookAddr,5,PAGE_EXECUTE_READWRITE,&dwOldCode)){
//直接覆盖内存数据
memcpy((void*)hookAddr, (void*)hookContext, 5);
VirtualProtect((void*)hookAddr,5,dwOldCode,&dwOldCode);
}
}catch(…){
puts(“内存写入失败”);
return;
}
}
void main(void)
{
if(getchar() == ‘h’){
hooktestCall();
}
//代码执行地址,先通过OD找到代码所在的偏移量
printf(“当前模块地址:%x”, GetModuleHandleW(NULL));
puts(“用于测试汇编hook代码”);
puts(“不能在前面改函数”);
testRealFunc1();
getchar();
}

偏移量是我在自己算出来,如果你编译我不知道是不是会改变,如果会改变请自行修改。算法就在注释里面还是比较好理解。

call 立即数 :这个是相对地址,我前面不知道这个逻辑,结果替换时候,用CE查看地址汇编发现指向未知地址,导致奔溃。所以需要我们自己写算法转换。

后面慢慢整理一个系列的文章,这样帮助没有接触过这类的技术人,我自己自学半个月,用c++去写辅助类产品,网上大多数都是易语言。vc 这类的文章很少,以前觉得很神奇,现在发现就是汇编改改代码的问题。