a.tm.k 发布的文章

[python] flash AMF 协议通讯脚本

#!/bin/env python
# -*- coding:utf-8 -*-

'''
  env: python2
  require: pyamf
  descript: 针对 blazds flex 的接口通讯模块
  author: delovt
  date: 2019-3-4 18:20:10
'''
import os,sys
import pyamf
import urllib2
import uuid
from pyamf import remoting
from pyamf import flex
from pyamf.flex import messaging

reload(sys)
sys.setdefaultencoding('utf-8')

def reader(d):
  dKeys = getattr(d, 'SMALL_ATTRIBUTES')
  for i in dKeys:
    print '[+] ' + dKeys[i] + ' -> ' + str(getattr(d, dKeys[i]))

def runer(v, c):
  # build data
  msg = messaging.RemotingMessage( messageId= str(uuid.uuid1()).upper(),
    clometOd = None,
    operation = v[2],
    destination = v[3],
    timeTolive = 0,
    timestamp = 0
  )
  msg.body = [c, 1, 17, flex.ArrayCollection(), 0] # 请求体, 需要手动构造
  msg.headers['DSEndpoint'] = v[4]
  msg.headers['DSId'] = str(uuid.uuid1()).upper()
  req = remoting.Request('null', body=(msg,))
  env = remoting.Envelope(amfVersion=pyamf.AMF3)
  env.bodies = [('/1', req)]
  # data = bytes[remoting.encode(env).read()]
  data = remoting.encode(env).read()
  # connect servlet
  url = v[1]
  req = urllib2.Request(url, data, headers = {'Content-Type': 'application/x-amf'})
  # parse reponse
  opener = urllib2.build_opener()
  resp = remoting.decode(opener.open(req).read())
  reader(resp.bodies[0][1].body)

def helper():
  print '[+]  helper Start'
  print 'usage: python attacker.py <address> <operation> <destination> <DSEndpoint>'
  print 'example: python attacker.py http://127.0.0.1:8080/amfcallback findPageBySQL PageDataService Null'
  print 'codeEditFrom: https://www.jianshu.com/p/0f3009021fd9'
  print '[-] helper End'

def main():
  if len(sys.argv) < 2 or sys.argv[1].lower() == '-h' or sys.argv[1].lower() == '--help':
    helper()
    exit(1)
  while True:
    command = raw_input('hibernate command: ')
    if command != 'quit' :
      runer(sys.argv, command)
    else:
      break

if __name__ == '__main__':
  main()

amf 请求包结构如下:
AMF3Proto-mask.bmp

[Win10] 系统未安装音频输出设备 - 已解决

win10 系统未安装音频输出设备 问题详情

win10 版本信息

OS 名称:  Microsoft Windows 10 教育版
OS 版本:  10.0.17134 暂缺 Build 17134

问题硬件信息

硬件描述: Realtek(R) Audio 
设备描述: Realtek High Definition Audio

系统存在小喇叭, 鼠标移动放上去后, 提示系统未安装音频输出设备.
检查以下两项

系统驱动 -> 所有驱动已正常安装, 不需要更新
设备管理器 -> 声音栏未发现硬件信息, 但在系统设备中存在感叹号设备

截图如下所示:
001.png
002.png
003.png

解决方案

具体怀疑是驱动问题, 但是无法彻底的卸载掉 win10 驱动, 也无法安装旧版本驱动.
首先关注具体的路径, 如下:

C:\Windows\System32\DriverStore\FileRepository\hdaudbus.inf_xxxx_xxxxxxxx
C:\Windows\System32\DriverStore\FileRepository\hdaudio.inf_xxxx_xxxxxxxxx
C:\Windows\System32\drivers

其中 System32\DriverStore\FileRepository 文件夹下留存着驱动程序文件
System32\drivers 文件夹则保存着目前需要调用的驱动程序.
流程如下:

  • 设备管理器中卸载掉带叹号的设备, 然后 "扫描检测硬件改动"
  • 通过 PE 或者类似的工具, 将 System32\drivers 文件夹中的 hdaudbus.sys/hdaudio.sys 重命名
  • 将 System32\DriverStore\FileRepository 中对应的 hdaudbus/hdaudio 中的 .sys 复制过来
  • 设备管理器中卸载掉带叹号的设备, 然后 "扫描检测硬件改动"
    如下图:

004.png

解决效果图

005.png

浏览器的一些小技巧

Firefox

Network filter
# 黑名单
domain:www.baidu.com regexp:^.*([^\.js|\.png|\.css|\.jpg])$

#白名单
domain:www.biadu.com regexp:^.*?(\.jsp|\.action|\.do)(\?){0,1}.*$

过滤掉 js/png/css/jpg 文件和非 www.baidu.com 的 URL 请求

[PWN] 栈溢出初见

0x1. 前置条件

此案例来源于 《0day安全: 软件漏洞分析技术》, 章节 -> 第2章.
程序源码如下:

#include <stdio.h>
#include <windows.h>
#define PASSWORD "1234567"

int verify_password(char *password) {
    int flag = -1;
    char buffer[44];
    flag = strcmp(password, PASSWORD);
    strcpy(buffer, password);  // over flowed here
    return flag;
}

void main() {
    int flag = 0;
    char password[1024];
    FILE * fp;
    LoadLibrary("user32.dll");
    if(!(fp = fopen("password.txt", "r"))) {
        exit(0);
    }
    fscanf(fp, "%s", password);
    flag = verify_password(password);
    if( flag ) {
        printf("fail\n");
    } else {
        printf("succss\n");
    }
}

编译环境: Windows XP SP3 + VC 6.0
调试环境: Windows XP SP3 + Ollydbg + UltraEdit / Win10 + IDA

0x2 栈溢出初见

IDA 打开程序后, F5 看一下源码和汇编代码走向.
主程序流程
可以看到 main 函数中并不对数据进行校验, 主要校验函数在 verify_password() 里.
main 函数将数据从 password.txt 中取出来然后以参数的形式传递给 verify_password().
数据校验函数
verify_password 函数主要做了两步操作, 第一步是 strcmp 比较函数;
第二步是 strcpy 复制函数, 而 strcpy 的执行并没有对参数进行任何的校验或者限制.
这里存在着溢出点. 我们看到这里用以 strcmp 比较的内置字符串为 "1234567", 在这下个断点.
001-bp-1234567.PNG
首先用字符串搜索插件搜索字符串, 然后双击字符串到达领空, F2 下断点, F9 执行程序到达断点处。
在 Ollydbg 的界面中, 可以看到 EBP/ESP/EIP 的各项数值. 其中:
EBP => 0x0012FB20, 栈基址
ESP => 0x0012FAA4, 栈顶
EIP => 0x0040103F, 下一条语句的地址
在界面的中间下部栈空间区域, 可以看到当前栈基址 0x0012FB20 保存着上一个栈的栈基址为 0x0012FF80.
在它的下面, 0x0012FB24 则保存着返回地址 0x00401118, 通过左下窗口的数据查看器可以看到,
0x00401118 为 main 函数的代码段, 此地址对应的代码为执行了 call test003.00401005 后的下一条语句.
可以确定的认为 test003.00401005 为 verify_password 函数地址.
本次栈溢出的目的主要通过 strcmp 函数, 覆盖返回地址, 劫持 EIP 的指向, 来达到我们控制程序以执行任意代码目的.

0x3 细节

002-exec-strcmp.png
F8 单步执行, 从断点处执行到 strcmp 函数执行完毕, strcmp 函数的返回值一般保存在 EAX,
003-rtn-strcmp.png
再次单步执行 2 次, 可以看到 verify_password 函数的内置变量 flag 的值变为了 1.
004-push-payload-01.png
接着往下走, strcmp 执行完后, 到了 strcpy 函数.
首先可以通过代码窗口看到, 先将 arg.1 的地址入栈.
其中 arg.1 的地址为 0x0012FB7C, 这里保存着 arg.1 的数据. 它的长度为 0x12FB7C ~ 0x12FBD4, 共 88D 的长度.
004-push-payload-02.png
往下走, 程序已经将 local.12 的地址入栈.
local.12 的地址为 0x0012FAF0, 它的长度为 0x12FAF0 ~ 0x12FB18. 共 40D 的长度.
显而易见, arg.1 的长度是 local.12 长度的 2 倍多, 将会导致将 local.12 以及后面的空间给覆盖掉.
004-push-payload-03.png
F8 单步执行, strcmp 执行完毕后, 可以看到栈空间已经完全变了样.
flag 和 EBP 被覆盖成了 0x90909090, 而最重要的返回地址, 则被覆盖成了 0x77D8692C.
005-PAYLOAD-EXEC.png
0x77D8692C 这个地址有一条关键指令. 叫做 JMP ESP.
当程序执行到 retn 时, retn 等价于 POP EIP, 把当前栈中, ESP 指向地址的值出栈, 赋给 EIP.
当我们利用 strcpy 将原本的返回地址 0x00401118 给覆盖为 0x77D8692C 时.
我们就完成了将程序进行劫持的步骤, 可以控制程序执行任意代码.
007-FINAL.png