吾爱汇编

 找回密码
 立即注册

QQ登录

绑定QQ避免忘记帐号

查看: 1286|回复: 10

[转载技术] 函数和call详解

[复制链接] 出处:52破解
459121520 发表于 2022-11-15 07:40 | 显示全部楼层 |阅读模式


教程类型:
函数和call详解



一、函数的概念
函数又叫子程序 或则方法,我们举个例子来说明函数的概念
如果我们一天的生活是一段代码的话,这段代码中包含吃饭,开车,工作,休息 ,  娱乐 等等.
其中有很多的事情是重复做的,比如吃饭,吃饭的过程可能是几十条代码,我们简略一下.
用printf 去模拟一下这段代码.
printf("做饭\n");
printf("吃饭\n");
printf("洗碗\n");
如果我们把这一段代码封装成一个整体,那么我们重复使用的时候也就方便了,代码也看起来清晰一些
原本几十条代码组成吃饭这个过程,现在被封装成一个整体,这个整体就是一个函数。
为什么需要函数呢?原因有两点:一是方便重复使用,二是代码更加清晰

1、函数体,这个整体要用{}括起来,这个整体叫做函数体

printf("做饭\n");
printf("吃饭\n");
printf("洗碗\n");

那么还需要什么呢?

2、函数名,比如吃饭,给这个函数起个名字,我们才能调用
吃饭

printf("做饭\n");
printf("吃饭\n");
printf("洗碗\n");


3、参数
这时候可能有的同学会问,吃饭虽然是一天中重复的动作,但是不是简单的重复啊,早上我们吃面包, 中午我们吃面条,是2个不同的动作,那不就不能重复利用了吗?
其实这就是子程序的参数,参数是可变的,由调用者提供。
吃饭(string 食物)
{
printf("做饭: %s\n", 食物.data());
printf("吃饭\n");
printf("洗碗\n");
}

4、返回值
还有同学可能会问那我如果想知道这个动作执行的结果呢,比如吃饭吃饱了吗?
其实这就是子程序的返回值
int 吃饭(string 食物)
{
printf("做饭 %s\n", 食物);
printf("吃饭\n");
printf("洗碗\n");
return 1;
}

5、最终函数的格式
return type  name(arguments)
{
body
}
举例:加法运算
int add(int a,int b)
{
return  a+b;
}

举例:测试字符是大写还是小写字母
int test(char ch)
{
int ret = 0;
if (ch >= 'A' && ch <= 'Z')
{
ret = 1;
}
else if(ch >= 'a' && ch <= 'z')
{
ret = -1;
}
return ret;
}

注意事项:
1.函数返回值,没有返回值void
2.函数名不能是关键字 例如if
函数的命名规则,每个单词大写开头(C++)
3.参数可以多个 类型+参数名  用 , 号隔开
4.函数体每句代码结束要用;
5.有返回值要return返回值

例如   输入半径,求圆的面积
#include
#include"windows.h"

float area(float r)
{
        float area = 3.14*r*r;
        return area;
}

int main()
{
        float r=0;
        scanf("%f",&r);
        float ret = area(r);
        printf("\n%f",ret);
        getchar();
        return 0;
}

二、Call
那什么是call呢,函数即是call, call就是函数.
只是不同语言中不同的称呼而已.
C++中叫函数, 汇编中叫call.

我们从反汇编窗口看看函数的汇编代码,来了解下子程序和call的对应关系

                               
登录/注册后可看大图


转到反汇编

                               
登录/注册后可看大图


PUSH C8 和push  64对应着传递参数 100和200,他的顺序可以注意一下,我们后面还会提到
(当然参数还有用寄存器传递的时候.我们很快就会看到)

call 001A1488  对应函数体地址.这句也可以当成函数名

                               
登录/注册后可看大图


先跳到1A1488又转到1A5F60 ,1A5F60 就是函数体首地址

                               
登录/注册后可看大图


如果有返回值,会存放在 函数体执行结束的 EAX寄存器中.
add  esp,8 是处理堆栈平衡, 我们这里暂时忽略,很快会讲到.
三、函数的定义和声明
函数定义必须放在函数调用的前面,否则找不到标识符.
例如:

                               
登录/注册后可看大图


有时候代码很多,有互相调用,我们很难确保谁在前面谁在后面.
例如call1调用call2  ,  call2又调用call1
这时候是会报错的.

怎么解决这个问题呢?
就涉及到了函数的声明和定义
这个时候我们就需要函数声明和函数定义分开的方法,这样就可以了.

                               
登录/注册后可看大图


把函数第一句拷贝出来 加个;即可

函数声明, 不带大括号 无函数体,也叫函数原型
函数定义 ,带大括号  有函数体,也叫函数实现.

一般函数声明放到头文件里,函数定义放到cpp里
这样别的文件想要使用,直接包含头文件就可以了,编译器会通过函数声明,自动帮我们找到函数定义.
如果
都放到CPP里不可以被其他CPP包含.
都放在头文件里,如果被多个CPP包含,就会重定义了.

四、Call的多层调用
函数可以调用函数,call可以调用call.
call其实很好理解,更直接的理解一段代码,某一段折叠了也可以理解成call,当然折叠的部分可以再折叠就是call调用的call
文件夹也一样,10个文件顺序执行,放到文件夹就是函数,文件夹里还可以包含文件夹.就是call调用的call
需要掌握以下3个指令
F10  不进入call    =  OD的F8  单步步过
F11  进入CALL   =  OD的F7   单步步入
shitf+F11   跳出  =  OD的CTRL+F9  执行到返回

理解shitf+F11(CTRL+F9 )执行到返回的含义:
我们先在CALL3(100);处下断  F11单步执行 看一下C++和反汇编执行的整个过程
然后再call1内下断  看看shitf+F11的过程

                               
登录/注册后可看大图


shift+F11跳出所到的位置就是调用完本层call出来以后的下一句

                               
登录/注册后可看大图


其实本质就是 shift+F11(CTRL+F9) 相当于 F10(F8)单步执行到汇编代码 retn ,执行完毕retn就到了这个位置,call下面的一句
一定要理解清晰shift+F11(CTRL+F9)的原理和执行过程
call2调用call1 ,call1里下断,返回的位置就是call2调用call1的下一句. 有的XDBG会设置执行到RETN而不是执行了RETN我们在点一次F8 就和上面一样了.

了解最简单的找call方式:
通过以上的调用关系,其实我们就掌握了最简单的找call方法
例如一个软件想跟别人或则服务器通信 ,必须要发包
那就会用到大三发包函数 send  sendto   WSASend,我们在这些函数上下断,断下返回就能找到调用他的功能call
(如果这三个都不断的时候,那是重新写的发包函数,也很容易找到,这个后面我们会有实例再讲解)
再例如一个软件点击按钮弹出信息框, 他就要用到MessageBox我们在这个函数上下断就可以 返回到相关的函数了.

打开我们的课件,课件点击按钮会弹出信息框

                               
登录/注册后可看大图


那么我们到MessageBoxA下断

                               
登录/注册后可看大图


下断

                               
登录/注册后可看大图


点击按钮断下

                               
登录/注册后可看大图


这个时候会卡死,是因为弹出的信息框卡住了,点掉就好了.
还有其他卡死的情况是因为 VM和到了线程头部等等

这个时候我们就可以利用ctrl+F9找到相关的call了,例如控件点击call等等
ctrl+F9返回的就是一系列调用的函数.

                               
登录/注册后可看大图


                               
登录/注册后可看大图


                               
登录/注册后可看大图


                               
登录/注册后可看大图


                               
登录/注册后可看大图


                               
登录/注册后可看大图


此时代码的调用过程就是666---->555---->444---->333---->222---->111---->MessageBoxA

我们还有2种取得调用关系的方法:
1、点击K(有时候不全不准,但是最快捷)
至上而下是从第一次返回到最后返回的关系

                               
登录/注册后可看大图

[Asm] [color=rgb(51, 102, 153) !important]纯文本查看 [color=rgb(51, 102, 153) !important]复制代码
调用堆栈:     主线程
地址       堆栈       函数过程                              调用来自                      结构
01B8ADD4   74E94361   包含apphelp.74E923EA                    apphelp.74E9435F              01B8ADD0
01B8ADF8   01064AB8   apphelp.74E94330                      任鸟飞逆.01064AB2                 01B8ADF4
01B8AF00   01064A05   任鸟飞逆.01035B07                         任鸟飞逆.01064A00                 01B8AEFC
01B8AFD4   01063CC1   任鸟飞逆.0102A252                         任鸟飞逆.01063CBC                 01B8AFD0
01B8B0D0   0108B381   包含任鸟飞逆.01063CC1                       任鸟飞逆.0108B37E                 01B8B0CC
01B8B19C   0108AA32   任鸟飞逆.01034B1C                         任鸟飞逆.0108AA2D                 01B8B198
01B8B248   0108E504   任鸟飞逆.0102C92B                         任鸟飞逆.0108E4FF                 01B8B244
01B8B2BC   010E57D6   包含任鸟飞逆.0108E504                       任鸟飞逆.010E57D3                 01B8B2B8
01B8B350   010C740D   任鸟飞逆.0101F08C                         任鸟飞逆.010C7408                 01B8B34C
01B8B368   010E8199   包含任鸟飞逆.010C740D                       任鸟飞逆.010E8193                 01B8B364



我们发现和之前的调用关系是一样的.

2、堆栈直接拿返回到(准确,但是速度教慢)
一般遇见VM没有办法CTRL+F9的时候,或则我们不想执行代码的时候直接从堆栈中点击跳转回上一层

外层call  和内层call 的关系
外层call 更完整,因为他执行了所有的代码.

内层call 绕过更多的判断代码,很容易理解,他只执行了部分代码,当然跳过了外层很多的判断
那么就更容易达到意想不到的功能,挖掘修复漏洞,最内层的函数是发包.

例如:一些功能最外层才有动作,内层只有结果没有动作,但是内层可以实现意向不到的功能.
例如没有了分解动作和读条达到秒分解,没有小腿的读时间直接退出等等

找到call以后验证是否正确的方法,标准有2个:1只有目标功能才断,2只断一次(当然也有特例,比如按键call断2次UP和DOWN).
五、函数约定
函数调用约定,是指当一个函数被调用时,参数是怎么传递的,平衡堆栈是怎么处理的.
这几种类型 :__stdcall__cdecl__fastcall
只要在函数名  前面加上 以上关键字即可
我们先来看看最常用的3种函数约定
[Asm] [color=rgb(51, 102, 153) !important]纯文本查看 [color=rgb(51, 102, 153) !important]复制代码
int __stdcall SdtCall(int a, int b, int c);
int __cdecl CdCall(int a, int b, int c);
int __fastcall FastCall(int a, int b, int c);
int __stdcall SdtCall(int a, int b, int c)
{
return  (a + b) * c;
}
int __cdecl CdCall(int a, int b, int c)
{
return  (a + b) * c;
}
int __fastcall FastCall(int a, int b, int c)
{
return  (a + b) * c;
}



                               
登录/注册后可看大图


我们用OD逆向分析一下3个call的区别
主要是传参方式  和 堆栈平衡方式的区别
1、stdcall: push 传递参数,ret平堆栈

                               
登录/注册后可看大图


                               
登录/注册后可看大图


2、cdecl:push 传递参数,call 外面用add esp,xxx 平堆栈(默认函数约定)

                               
登录/注册后可看大图


3、fastcall: ecx+edx+push 传递参数, ret 平堆栈

                               
登录/注册后可看大图


                               
登录/注册后可看大图


其他约定我们可以VS里直接调试来看一眼__thiscall,__nakedcall(__declspec(naked)),__pascal,__vectorcall
__thiscall只能出现在非静态成员函数声明中,我们后面学习中再讲
__declspec(naked),是用来告诉编译器函数代码的汇编语言为自己所写,不需要编译器添加任何汇编代码
是编译器直接拿来用的汇编函数代码, 所有东西都需要我们自己构造,必须使用retn指令返回
__pascal 关键字 PASCA,VC中已经完全__stdcall替代.

                               
登录/注册后可看大图


__vectorcall

                               
登录/注册后可看大图


无论什么函数约定
其实注意的就是两件事
第一,从函数开始执行前的第一句代码开始,到函数执行完毕,保证他的ESP不发生变化,也就是堆栈平衡
如果堆栈不平衡,会导致堆栈存放的数据位置错乱,在返回的时候执行到错误指针导致崩溃,我们在堆栈详解的时候会详细讲到.
第二,传递参数的方式,无非就是 可能有ecx,可能有edx ,可能有push
其实我们通过平衡堆栈的数值就知道,push了几个参数, 而ecx和edx我们可以观察以及测试
当然在实战过程中还有其他寄存器也有可能有用,我们后面会讲.

六、内联汇编
学习锻炼简单的内联汇编

内联汇编
内联汇编,指在C/C++中插入汇编语言。
1.可以帮我们在C/C++中插入汇编代码。
2.可以帮我们调用目标程序的子程序(CALL)。
3.可以协助我们偷功能。

内联汇编写法很容易
__asm{},把自己想插入的汇编代码直接按照汇编的语法编写即可。
注意:
1.内联汇编中的数值不是默认16进制,写16进制要加0x , 代码注入器里不用加0x
2.代码注入器中测试可以的代码,到内联汇编中要做一定的修改
最基本的就是   call  0x0097A252改成 mov eax,0x0097A252  call eax
call  立即数  语法是不合法的   需要用寄存器转一下

例子1,调用无参数函数

                               
登录/注册后可看大图


例子2,调用有参数函数

                               
登录/注册后可看大图


默认cdecl函数约定,所以注意我们的传参和平堆栈方式
更深入的内联汇编问题,我们内联汇编详解再说, 因为需要更详细的堆栈知识.
七、分析call编写call的步骤
拿课程call 当例子

                               
登录/注册后可看大图


第一步、写call地址,相当于写函数名  
call无非就两种
第一种call 常量,我们直接照抄即可
第二种call 寄存器(虚函数等我们后面会讲)如果寄存器的值是固定的,我们可以直接写常量.
如果不是固定的,需要像追数据一样追其偏移表达式.
代码写成:   
call  0x0097A252

第二步、根据堆栈平衡判断要写几个PUSH
我们学习了函数约定以后,知道无论什么函数约定,无论什么样的平栈方式,目的都只有一个就是堆栈平衡.
为什么一定要堆栈平衡,堆栈不平衡会怎么样?我们堆栈详解中再来一步步看,其实很简单.
无论是  ret 4*n  还是 add esp,4*n  都是表示 这个call有n个push, 而不是肉眼观察call上面有几个push是不准确的.
课程例子中我们可以看到是外平栈 add esp,4
那么就是上面只有一个PUSH
代码进一步写成:
push  xxxx
call 0x0097A252

第三步、判断ecx,edx是否有用
根据fastcall函数约定我们知道ecx,edx是有可能传递参数的
所以我们应该判断下是否需要给ecx,edx传递值
两种方法:
1.进call直接观察是否用到.
例如这个call里面ecx直接被清零了,所以很明显是没有用的.

                               
登录/注册后可看大图


2.暴力修改法,就是我们在call上下断,断下以后修改ecx或则edx的值,看call是否可以顺利执行,如果可以就是没有用到.
否则不会顺利执行,甚至崩溃.
代码依然是:
push  xxxx
call 0x0097A252

第四步、堆栈平衡   
如果是通过retn xxxx平衡的堆栈,我们就不需要写了,因为call内部帮我们执行了.
如果是通过add esp,xxxx平衡的堆栈我们就把代码写下来,不写相当于堆栈不平衡.
代码进一步写成:
push  xxxx
call 0x0097A252
add esp,4


第五步、最好在代码的前后加上pushad  popad 保护好寄存器值
代码进一步写成:
pushad
push  xxxx
call 0x0097A252
add esp,4
popad

第六步、填写参数值
参数有很多种情况,后面我们在详细分析
这里面是固定的4B0,我们先填写上即可
pushad
push  4B0
call 0x0097A252
add esp,4
popad

第七步、如果调用依然存在问题
那么就是其他寄存器有可能需要赋值(可以用暴力修改法验证) 或则 需要主线程调用而已.


第八步、用代码注入器验证

                               
登录/注册后可看大图


发现没问题

第九步、编写C++代码
[Asm] [color=rgb(51, 102, 153) !important]纯文本查看 [color=rgb(51, 102, 153) !important]复制代码
__asm
{
pushad
push  0x4B0
mov eax,0x0097A252
call eax
add esp,4
popad
}



细节小问题
1、注入一个call,为什么在这个call上下断不断?
因为是调用他里面的代码,所以里面下断会断,外面不会断.
2、加pushad  popad还需要堆栈平衡吗?需要
因为popad能够还原的根本原因还是堆栈平衡,如果堆栈变化了,popad就没有办法还原了.
3、可以提前保存ESP到其他地址,调用完call还原esp,就不用考虑堆栈平衡了,下面就是防止堆栈不平衡的注入代码
[Asm] [color=rgb(51, 102, 153) !important]纯文本查看 [color=rgb(51, 102, 153) !important]复制代码
对的和错误为什么?思考一下!
前提是12345678 是一个可读可写的地址哦!
对的写法
pushad
mov [12345678],esp
push  0x4B0
call 0x0097A252
add esp,4==== 去掉
mov esp,[12345678]
popad

错的写法
mov [12345678],esp
pushad
push  0x4B0
call 0x0097A252
add esp,4==== 去掉
popad
mov esp,[12345678]



>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
附练习:
1.KDXY心跳包筛选.
2.找吃药call,验证call是否正确,分析call调用流程,从键鼠消息到发包.
3.调用和编写吃药CALL.
4.KDXY自动吃药线程.
吃药call

                               
登录/注册后可看大图


分清楚PUSH是谁的参数,按照我们的步骤即可,不用管连call(连call不过是中间可以调用其他call 来帮我们取值)
代码注入器
[Asm] [color=rgb(51, 102, 153) !important]纯文本查看 [color=rgb(51, 102, 153) !important]复制代码
push 0
push 0
call 004FACD0
mov ecx,eax
call 00491C50



MFCDLL 代码

                               
登录/注册后可看大图


八、CALL参数的各种情况
参数无非就是值或则指针

1、常量值参数,固定写死即可(当然你可以尝试修)

                               
登录/注册后可看大图


2、常量值和常量指针要区分开

                               
登录/注册后可看大图


这样直接调用是没有反应的,因为他只是一个地址,就和快递箱子一样,call要的是里面的值

                               
登录/注册后可看大图


因为他是一个指针,函数是需要里面的值
我们发现执行的时候里面是0x64

                               
登录/注册后可看大图


所以我们有两种方法,要不然内存地址里写入0X64 调用,要不然自己申请个地址写入0x64调用

                               
登录/注册后可看大图


这样就可以了
当然还有浮点数值,看起来像指针,也有可能很大的整数值像指针,没有什么是绝对的,需要我们有一定的观察能力和测试能力

3、变量值参数,我们根据需要自己提供

                               
登录/注册后可看大图


变量我们可以在传递的时候,自己随意修改,当然要含义,例子中我们是一个int  一个float 意义是显示出来
例如吃药call  我们传递ID 或则传递药品位置,这些都是我们随意修改的.


4、变量指针,需要我们自己申请

                               
登录/注册后可看大图


这里我们发现参数是指针而且是变化的,所以需要我们自己申请指针写入参数

5、常量或则变量,参数结构体指针
这个结构体指针无论是否是变化的其实我们也是可以自己mlloc或则new的
有的时候会有结构体大小的参数,例如包长,但是如果没有,我们判断结构体多大是一个比较麻烦的事情.

                               
登录/注册后可看大图


6、对象指针,需要追偏移表达式

                               
登录/注册后可看大图


光靠观察完全区分清楚上面所有情况是不可能,需要我们多锻炼测试才能应用的得心应手


九、特殊类型的call注意事项
1、 多个push 混搭区分哪个是我们的push.

                               
登录/注册后可看大图


2、所谓连call ,不过是要利用上面的call 取得返回值而已,还是一个call.

                               
登录/注册后可看大图


                               
登录/注册后可看大图


3、堆栈统一平衡的连call,要区分平衡堆栈.

                               
登录/注册后可看大图


编写代码堆栈不平衡这里会崩溃,但是会输出信息
4、不用push传递参数,其他寄存器当参数
不传递esi成功不了,我们可以尝试暴力修改法

                               
登录/注册后可看大图


十、找call的各种方法
1、发包函数等api函数找call
一般就是send 或则发包函数通过调用关系找call
2、内存的访问找CALL
这个call内部访问了什么数据
3、参数找CALL
这个call会有什么样的参数
这种比较特殊,可能需要我们F7往下找
第一种我们已经尝试过很多次了,我们来尝试下第二种和第三种

KDXY寻路call
搜索 寻路目的地坐标,发现有基地址,直接下写入断,属于第二种或则第三种都有可能
或则
(寻路状态搜索1    4byte
停止状态搜索0    4byte) 属于第三种
找到3个地址,这个状态实际是走路状态,走路也改变
第一个地址下写入断没有断到寻路call
第二个地址下写入断断到了寻路call)

                               
登录/注册后可看大图


正常的写法
push 0
push 1
push 00D1F930============目的地坐标
push 00D3EB40===============传递我们当前的坐标进去
mov ecx,00D0DEC8
call 00445AB0

十一、用堆栈架构结构体
1、确定堆栈平衡  构建call的框架
push
push
push
push
mov ecx,
call 00445AB0

2、分析参数
push  0
push  1
push  00D1F930  目的地
push  xxxx   出发的地址
mov ecx,00D0DEC8
call  00445AB0

3、需要构造的东西处理一下

mov eax,[00D0DF1C]
mov eax,[eax+1C]
mov eax,[eax+28]
mov ecx,[eax+44]
push ecx
mov ecx,[eax+40]
push ecx
mov ecx,[eax+3C]
push ecx
lea edx,[esp]

push 0
push 1
push 00D1F930
push edx
mov ecx,00D0DEC8
call 00445AB0
add esp,0C====为自己构造的堆栈平栈


十二、CALL调用出现问题的时候  几种情况的原因   
1、CALL成功 但崩溃  堆栈不平衡
2、CALL不成功 没崩溃 非重要参数不正确
3、CALL不成功 崩溃 重要参数 尤其ECX不正确
4、CALL时而成功  时而不成功   需要主线程环境调用  后面会讲

十三、CALL锻炼
万能按键CALL
扫描字节型背包是否打开标志位
下BYTE写入断
断到按键CALL
[Asm] [color=rgb(51, 102, 153) !important]纯文本查看 [color=rgb(51, 102, 153) !important]复制代码

0062968E    53              push    ebx                              ; 300001   300001
0062968F    55              push    ebp                              ; 42    42
00629690    50              push    eax                              ; 100     102
00629691    8BCE            mov     ecx, esi
00629693    E8 58000000     call    006296F0                         ; 万能按键call


[Asm] [color=rgb(51, 102, 153) !important]纯文本查看 [color=rgb(51, 102, 153) !important]复制代码

push 300001
push 42
push 100
mov ecx,20BD4AE0
call 006296f0

sleep(100)

push 300001
push 62
push 102
mov ecx,20BD4AE0
call 006296f0



换装备CALL(封包call)

                               
登录/注册后可看大图

[Asm] [color=rgb(51, 102, 153) !important]纯文本查看 [color=rgb(51, 102, 153) !important]复制代码
mov edx,[00D0DF1C]
mov ecx,[edx+20]
push 4
push 346BB370==============申请的地址  代码注入器的时候 我们OD里随意找一个地址
call 0067D4E0



malloc和free

                               
登录/注册后可看大图


控件输入call
搜索账号编辑框的字符长度,剩余3个
其中有2个是光标的位置,真正字符长度只有1个地址

                               
登录/注册后可看大图


对其下写入断,返回既有控件输入call,可以用来输入账号密码,喊话聊天等等
返回的第一个call 就是

                               
登录/注册后可看大图


数据不带着你们追了,后面学完数据结构再追

                               
登录/注册后可看大图


控件点击call
用发包函数返回即可,但是不是所有的发包动作都能返回,要调用相对简单的动作比较容易返回
比如删除角色,创建角色登录等一般不行
删除角色返回到的控件点击call

                               
登录/注册后可看大图


                               
登录/注册后可看大图


push 334b0224
mov ecx,11616380
mov eax,00C0796C
call [eax+30]




注:本教程比较的基础,我也是出于学习分享此文章内容搬砖于其他论坛,作者 fakename.png 仅做自己论坛收藏贴用,
转载请标注来源


评分

参与人数 13HB +12 THX +4 收起 理由
消逝的过去 + 2
虚心学习 + 1 [吾爱汇编论坛52HB.COM]-软件反汇编逆向分析,软件安全必不可少!
白子希 + 1
Jawon + 1
李卓吾 + 1
行行行行行行 + 1
bnjzzheng + 1 [吾爱汇编论坛52HB.COM]-学破解防破解,知进攻懂防守!
水清流 + 2 + 1 [吾爱汇编论坛52HB.COM]-吃水不忘打井人,给个评分懂感恩!
VipDongle + 1
Cerolluo + 1 [吾爱汇编论坛52HB.COM]-感谢楼主热心分享,小小评分不成敬意!
王奥森 + 1
zxjzzh + 1 [吾爱汇编论坛52HB.COM]-学破解防破解,知进攻懂防守!
WolfKing + 1

查看全部评分

吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
 楼主| 459121520 发表于 2022-11-15 07:43 | 显示全部楼层

第一次转载,但是图片在编辑的时候是没问题的,为何发表的时候会被拉长
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
WolfKing 发表于 2022-11-15 14:05 | 显示全部楼层

楼主转载辛苦了 也是一个苦力活
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
 楼主| 459121520 发表于 2022-11-15 14:06 | 显示全部楼层

就叫东子吧 发表于 2022-11-15 14:05
楼主转载辛苦了 也是一个苦力活

只要作者不来找麻烦就是最好的了,我这里嘛也就当做个收藏笔记了,就是不知道为啥那些图片会被拉成这个样子
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
Cerolluo 发表于 2022-11-16 15:54 | 显示全部楼层

谢谢分享!!!!!!!!
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
水清流 发表于 2022-11-21 14:43 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
头像被屏蔽
别管我了行 发表于 2022-11-23 17:38 | 显示全部楼层

提示: 作者被禁止或删除 内容自动屏蔽
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
bnjzzheng 发表于 2022-12-23 15:05 | 显示全部楼层

感谢分享。。
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
曾经沧海 发表于 2023-2-23 21:34 | 显示全部楼层

牛啊,感谢分享
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
一生逍遥 发表于 2023-3-11 08:05 | 显示全部楼层

这绝对是实用技术!
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

警告:本站严惩灌水回复,尊重自己从尊重他人开始!

1层
2层
3层
4层
5层
6层
7层
8层
9层
10层

免责声明

吾爱汇编(www.52hb.com)所讨论的技术及相关工具仅限用于研究学习,皆在提高软件产品的安全性,严禁用于不良动机。任何个人、团体、组织不得将其用于非法目的,否则,一切后果自行承担。吾爱汇编不承担任何因为技术滥用所产生的连带责任。吾爱汇编内容源于网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除。如有侵权请邮件或微信与我们联系处理。

站长邮箱:SharkHeng@sina.com
站长QQ:1140549900


QQ|RSS|手机版|小黑屋|帮助|吾爱汇编 ( 京公网安备11011502005403号 , 京ICP备20003498号-6 )|网站地图

Powered by Discuz!

吾爱汇编 www.52hb.com

快速回复 返回顶部 返回列表