C语言数据类型 裸函数
1 2 3 4 void __declspec(naked) Plus(){ }
跟空函数不一样
裸函数依旧是个call,不过里面没有内容
1 2 3 4 void __declspec(naked) Plus(){ __asm ret }
这样的就可以正常运行,因为这样会retn
手写汇编实现Add函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 int __declspec(naked) Plus(int x, int y){ __asm { push ebp mov ebp,esp sub esp,0x40 push ebx push edi push esi mov eax,0xCCCCCCCC mov ecx,0x10 lea edi,dword ptr ds:[ebp-0x40 ] rep stosd mov eax,dword ptr ds:[ebp+0x8 ] add eax,dword ptr ds:[ebp+0xc ] pop esi pop edi pop ebx mov esp,ebp pop ebp ret } }
调用约定 调用约定 参数压栈顺序 平衡堆栈 __cdecl 从右至左入栈 调用者清理栈 __stdcall 从右至左入栈 自身清理堆栈 __fastcall ECX/EDX传送前两个 剩下:从右至左入栈 自身清理堆栈
__cdecl 外平衡
1 2 3 4 push 1 push 2 call add esp,8
1 2 3 4 int __cdecl Plus (int a,int b) { return a+b; }
__stdcall 内平衡
1 2 3 push 1 push 2 call //call里平衡 ret
1 2 3 4 int __stdcall Plus (int a,int b) { return a+b; }
__fastcall 利用寄存器传参
1 2 3 mov edx,2 mov ecx,1 call
1 2 3 4 int __fastcall Plus (int a, int b) { return a+b; }
裸函数实现 1 2 3 4 5 6 7 int plus (int x, int y, int z) { int a=2 ; int b=3 ; int c=4 ; return x+y+z+a+b+c; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 int __declspec(naked) Plus(int x, int y,int z) { __asm { push ebp mov ebp,esp sub esp,0x40 push ebx push edi push esi mov eax,0xCCCCCCCC mov ecx,0x10 lea edi,dword ptr ds:[ebp-0x40] rep stosd mov eax,2 add eax,3 add eax,4 add eax,dword ptr ds:[ebp+0x8] add eax,dword ptr ds:[ebp+0xc] add eax,dword ptr ds:[ebp+0x10] pop esi pop edi pop ebx mov esp,ebp pop ebp ret } }
可以修改入口点 入口点实际不是main
link->entrypoint
查找main方法,可以push 3个参数的
数据类型与数据存储 C语言数据类型 汇编数据宽度 char byte short word int dword long dword
无符号跟有符号,在内存中存储的是一样的,根据使用的人来决定
默认有符号,类型转换–比较大小–数学运算要注意
有符号跟无符号,比较会改掉,jbe跟jle 低于等于,小于等于
浮点类型 这部分就是计算机组成原理
float的存储方法
12.5 在内存中存储为
整数部分: 12
计算 余数 12/2=6 0 6/2=3 0 3/2=1 1 1/2=0 1
从下往上: 1100
小数部分: 0.5
从上往下:1
1100.1=1.1001*2的3次方
1位符号位 中间8位指数 后面23位尾数
尾数从左往右写就行
中间8位开头,左移为1,右移为0,
后面7位,存储指数-1,比如3次方,就是存10,如果是-2次方就是-3,也就是fd, 11111101,然后只取后7位
127 +(3) = 130 = 0x82 = 1000 0010 这里直接加指数
0 10000010 10010000000000000000000
0100 0001 0100 1000 0000 0000 0000 0000
41480000
如果是-12.5呢
就变成
1100 0001 0100 1000 0000 0000 0000 0000
C1480000
将CallingConvention.exe逆向成C语言 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 int __fastcall Add5 (int num1, int num2, int num3, int num4, int num5) { int result1 = Add3(num1, num2, num3); int result2 = Add2(num1, num2); return Add2(result1, result2); } int __cdecl Add2 (int num1, int num2) { return num1+num2; } int __stdcall Add3 (int num1, int num2, int num3) { return num1+num2+num3; } int main () { int result1 = Add5(1 ,3 ,4 ,6 ,7 ); printf ("%d" , result1); }
编码 ASCII 英文字符
GB2312或GB2312-80 中文字符,两个字节一个汉字
练习 截取字符串 比如 china中国verygood天朝nice
fn(5) = china
fn(6) = china中
fn(8) = china中国v
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include <stdio.h> #include <string.h> char str[]= {"china中国verygood天朝nice" };int getString (int length) { int have=0 ; int all = sizeof (str)/sizeof (char ); char temp[3 ]; for (int i=0 ; have < length && i < all; i++) { if (str[i] >= 'A' && str[i] <= 'z' ) { printf ("%c" , str[i]); } else { printf ("%c%c%c" , str[i], str[i+1 ], str[i+2 ]); i += 2 ; } have += 1 ; } } int main () { getString(16 ); return 0 ; }
指针做乘法运算 1 2 3 4 5 6 7 8 9 #include <stdio.h> int main () { int a=1 ; int *result = (int *)((long )&a * 32 ) ; printf ("%p" , result); return 0 ; }
原来强转int *老是说信息丢失报错,改成long就不报错了
本文作者 :NoOne本文地址 : https://noonegroup.xyz/posts/27709fc2/ 版权声明 :转载请注明出处!