首页
社区
课程
招聘
[原创]CTF2017 第五题 独行孤客CrackMe 解题报告
2017-6-11 01:27 2470

[原创]CTF2017 第五题 独行孤客CrackMe 解题报告

2017-6-11 01:27
2470

CTF2017 第五题 独行孤客CrackMe

前言

这题为比较基本的静态反汇编,IDA 的基本功,鉴于大家肯定会发很多代码截图,为看雪论坛空间着想,我还是不重复发图了,发下流程和代码就行

流程

  1. 程序为未加壳的 VC6 MFC 程序

  2. 程序在 OnInitDialog 对话框初始化函数中释放 DRV 资源到当前目录 vmxdrv.sys 文件中,因为这是一个 32位驱动,所以题目说明了,并且程序启动也会检验是否在 XP 下运行,然后安装该驱动并且删除原文件

  3. 这个驱动功能比较简单

    • 接受 0x222004 控制消息,相当于初始化
    • 接收 write 请求,将数据进行某种变换(参考代码),然后保存 MD5 数组
    • 接收 read 请求,当没有前面的保存时输出固定数组,有则输出保存数组
  4. 在对话框的回车响应函数里执行

    • 将输入翻转,并且转成小写
    • 判断输入是否为6位(这么短明显让我们暴力啊),判断是否有调试器附加
    • 将翻转的输入 write 进驱动,并把读取 MD5 结果转成 HEX 字符串(小写)
    • 把上一步的 HEX 字符串再次进行 MD5,把结果转成 HEX 字符串(小写)
    • 从上一步的 HEX 字符串的第2位(0开始),取长度10(相当与5个字节的 HEX 字符串),与 888aeda4ab,对比

代码

因为会将输入转成小写,在暴力代码的生成部分我只组合了数字和小写字母,没有组符号(应该不会这么变态吧),该代码在 3720QM 下 160w/s 的速度

package main
import (
	"bytes"
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"os"
	"sync/atomic"
	"time"
)
var jobs = make(chan []byte, 6)
func build(s []byte) (r []byte) {
	r = make([]byte, len(s))
	copy(r, s)
	for i := range r {
		if i == 0 {
			r[i]++
			continue
		}
		r[i] += byte(i)
	}
	return
}
var count uint64
func run() {
	for {
		data := <-jobs
		b := build(data)
		t := md5.Sum(b)
		t = md5.Sum([]byte(hex.EncodeToString(t[:])))
		if bytes.Equal(t[1:6], []byte{0x88, 0x8a, 0xed, 0xa4, 0xab}) {
			fmt.Println(string(data), hex.EncodeToString(t[:]))
			os.Exit(0)
		}
		atomic.AddUint64(&count, 1)
	}
}
func NextIndex(ix []int, lens int) {
	for j := len(ix) - 1; j >= 0; j-- {
		ix[j]++
		if j == 0 || ix[j] < lens {
			return
		}
		ix[j] = 0
	}
}
func gen() {
	var a []byte
	for i := 0x21; i <= 0x7e; i++ {
		// 之前想弄个大范围,范围太大太慢放弃了
		// if i >= 0x41 && i <= 0x5A {
		// 	continue
		// }
		if (i >= 0x30 && i <= 0x39) || (i >= 0x61 && i <= 0x7a) {
			a = append(a, byte(i))
		}
	}
	k := 6
	lens := len(a)
	for ix := make([]int, k); ix[0] < lens; NextIndex(ix, lens) {
		r := make([]byte, k)
		for i, j := range ix {
			r[i] = a[j]
		}
		jobs <- r
	}
}
func process() {
	var last uint64
	for {
		now := atomic.LoadUint64(&count)
		fmt.Println(now, now-last)
		last = now
		time.Sleep(1 * time.Second)
	}
}
func main() {
	for i := 0; i < 8; i++ {
		go run()
	}
	go gen()
	process()
}



[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

收藏
点赞3
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回