C语言函数实现的另类方法
在前面看过那个BT的Javascript程序后,我们来看一个C语言的,相信大家还记得输出从1到1000的数最后的那个示例,本站还有很多这样的示例,如:变态的hello word,如何教新手编程,还有恐怖的C++,在下面这个示例面前,神马都是浮云。
下面这个示例向你展示了如何写一个swap()函数(把两个值交换),这段代码在我的Linux下的 gcc v4.1.1下可以正确编译通过,连一个Warning都没有,而且可以正确工作。我能说什么?!C语言并不疯狂,疯狂的是程序员。
#include <stdio.h> void(*swap)() = (void(*)()) "\x8b\x44\x24\x04\x8b\x5c\x24\x08\x8b\x00\x8b\x1b\x31\xc3\x31\xd8\x31\xc3\x8b\x4c\x24\x04\x89\x01\x8b\x4c\x24\x08\x89\x19\xc3"; int main(){ // works on GCC 3+4 int a = 37, b = 13; swap(&a, &b); printf("%d %d\n",a,b); }
其实,这种用字符串来实现函数的方法,在原理上是很好理解的。
字符串就是一段内存空间,把一个字符串指针强转成函数指针,那么这个指针所指向的内容就是各种指令,因此,那堆乱七八糟的东西说白了就是汇编。8086的汇编。你可以使用ndisasm来看看。
# ruby -e "print \"\x8b\x44\x24\x04\x8b\x5c\x24\x08\x8b\x00\x8b\x1b\x31\xc3\x31\xd8\x31\xc3\x8b\x4c\x24\x04\x89\x01\x8b\x4c\x24\x08\x89\x19\xc3\"" | ndisasm -u - 00000000 8B442404 mov eax,[esp+0x4] ; load pointers to two parameters into eax, ebx 00000004 8B5C2408 mov ebx,[esp+0x8] 00000008 8B00 mov eax,[eax] ; load values of two parameters from pointers (*eax, *ebx) into eax, ebx 0000000A 8B1B mov ebx,[ebx] 0000000C 31C3 xor ebx,eax ; swap two values (eax, ebx) using xor trick 0000000E 31D8 xor eax,ebx 00000010 31C3 xor ebx,eax 00000012 8B4C2404 mov ecx,[esp+0x4] ; load pointer to param 1 into ecx 00000016 8901 mov [ecx],eax ; store swapped value 1 (eax) into param 1 (*ecx) 00000018 8B4C2408 mov ecx,[esp+0x8] ; load pointer to param 2 into ecx 0000001C 8919 mov [ecx],ebx ; store swapped value 2 (ebx) into param 2 (*ecx) 0000001E C3 ret
注意:这段汇编中使用了XOR而不是引入第三个变量来完成了变量值的交换。
关于XOR的方式,参看下面的示例:
a = a^b; b=a^b; a=b^a;
或者更为简单的:
a^=b^=a^=b;
(全文完)
关注CoolShell微信公众账号和微信小程序
(转载本站文章请注明作者和出处 酷 壳 – CoolShell ,请勿用于任何商业用途)
——=== 访问 酷壳404页面 寻找遗失儿童。 ===——
《C语言函数实现的另类方法》的相关评论
换成 64 位还能编译吗?哈哈~
shellcode
xchg eax,ebx
学不好C呀
一开始还以为 ruby 什么时候可以反汇编了,结果拖到后面,华丽丽的 ndisasm
让我想起了一句话GCD:
while (b) b ^= a ^= b ^= a %= b;
“那堆乱七八糟的东西说白了就是汇编。” — 这个描述有点不科学!
“那堆乱七八糟的东西说白了就是机器码。” — 这样才对吧?
和thunk有点类似么,数据和代码本无界限~
不过linux内核不是有保护的么?数据页的内容不让执行,代码页的不让修改!
哪位大侠知道这种保护linux上怎么去设置,也就是说表现为代码侧是怎么样的?
“那堆乱七八糟的东西说白了就是汇编。” — 这个描述有点不科学!
“那堆乱七八糟的东西说白了就是机器码。” — 这样才对吧?
和thunk有点类似么,数据和代码本无界限~
不过linux内核不是有保护的么?数据页的内容不让执行,代码页的不让修改!
哪位大侠知道这种保护linux上怎么去设置,也就是说表现为代码侧是怎么样的?
PS: 评论没法成功重新发的时候怎么提示说我好像发过类似评论?— bug啊~~~
小心DEP……
这类技巧权当娱乐就好了,千万别让孩子们觉得是在鼓励他们写出“奇妙”的程序。
另外,很严重的一个问题是,这个交换内存的方法,当传入a和b的地址是同一个地址时,就杯具了。
如果a和b指向的是同一个内存地址的话,这么写swap不好使.
我真的试了,段错误。
这是shellcode,黑客常用手法,所以现在linux和windows等加了DEP防止栈执行。
这个a^=b^=a^=b是有问题的,不妨看看
http://c-faq.com/expr/xorswapexpr.html
@杭州-木风
这种字符串的定义方式是把东西放到了正文段的上半部,还是在代码部分呢,没在数据部分。
果然是 SMC手法
做3次异或的方法不如用临时变量高效
其实也可以这么写:
void swap(int *a,int *b)
{
__asm{
push a
push b
pop a
pop b
}
}
shellcode ,大学的时候看老师演示过,目瞪口呆啊!
以前写过这个,在mingw gcc 3.4.5 下测试通过
#include
unsigned int main[]={0x0000a268,0xb8909000,(int)(void*)putchar,0x6858D0FF,0x000000e1,0xb8909090,
(int)(void*)putchar,0xb858d0ff,(int)(void*)getchar,0xc390d0ff};
a^=b^=a^=b;行为undefined,两个顺序点之间变量值多次改变.
shellcode 最基本的东西