├── ics └── pcap │ ├── asn_to_hash.rb │ ├── tcp_payload_filter.rb │ ├── mms_extract_file.rb │ └── ics_analysis.rb ├── misc ├── pcap │ ├── mots_check.rb │ ├── tsc_tspl_printer.rb │ ├── usbmouse.rb │ └── usbkeyboard.rb ├── encoder │ ├── morese_decode.rb │ ├── base92.rb │ └── brainfuck.rb ├── image │ └── png_size_recover.rb ├── compress │ ├── zipfake.rb │ └── rarfake.rb └── stego │ ├── zwsp-steg.rb │ └── stegosaurus.py ├── crypto ├── shiro_rememberMe_decrypt.rb ├── weblogic_password.rb ├── weblogic_password.py └── shiro_keys.txt ├── README.md └── awd └── scanner ├── synproxy-scan.rb └── old-synproxy-scan.py /ics/pcap/asn_to_hash.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # 3 | # Author L 4 | # 5 | 6 | require 'awesome_print' 7 | 8 | filename = ARGV[0] 9 | value_name = ARGV[1] 10 | 11 | unless filename && value_name 12 | abort <<~EOF 13 | Usage: ./asn_to_hash.rb 14 | EOF 15 | end 16 | 17 | data = File.read(filename).match(/#{value_name}\s+::=\s+CHOICE\s+{(.*?)}/m) 18 | 19 | abort '[!] Not Find' unless data 20 | 21 | hash = {} 22 | data[1].each_line do |line| 23 | line.strip! 24 | next if line.start_with? '--' 25 | if line =~ /(.*?)\s+\[(.*?)\]/ 26 | hash[$2] = $1 27 | end 28 | end 29 | 30 | print "#{value_name} = " 31 | ap hash 32 | -------------------------------------------------------------------------------- /ics/pcap/tcp_payload_filter.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # 3 | # Author L 4 | # 5 | 6 | pcap_file = ARGV[0] 7 | display_filter = ARGV[1] 8 | filter_regexp = ARGV[2] 9 | filter_regexp = Regexp.new(filter_regexp) if filter_regexp 10 | 11 | separator = "%6s #{'=' * 75}" 12 | 13 | unless pcap_file && display_filter 14 | abort <<~EOF 15 | Usage: ./tcp_payload_filter.rb [filter_regexp] 16 | EOF 17 | end 18 | 19 | `tshark -r #{pcap_file} -Y '#{display_filter}' -Tfields -e frame.number -e tcp.payload`.each_line do |line| 20 | num, hex_data = line.chomp.split("\t") 21 | raw = [hex_data].pack 'H*' 22 | 23 | if filter_regexp 24 | if raw.match?(filter_regexp) 25 | puts separator % num 26 | puts raw 27 | end 28 | else 29 | puts separator % num 30 | puts raw 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /misc/pcap/mots_check.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # 3 | # Author L 4 | # 5 | 6 | require 'oj' 7 | 8 | pcap_file = ARGV[0] 9 | 10 | abort "Usage: ./mots_check.rb " unless pcap_file 11 | 12 | json_data = `tshark -r '#{pcap_file}' -Y 'tcp.payload && tcp.flags == 0x18' -T json -e frame.number -e tcp.seq -e tcp.ack -e tcp.payload -e tcp.dstport -e tcp.srcport -e ip.src -e ip.dst` 13 | 14 | mots = [] 15 | json = Oj.load(json_data).map{|x| x['_source']['layers'].transform_values(&:first) } 16 | json.each_cons(2) do |i, j| 17 | ii = i.values_at('ip.src', 'ip.dst', 'tcp.srcport', 'tcp.dstport', 'tcp.seq', 'tcp.ack') 18 | jj = j.values_at('ip.src', 'ip.dst', 'tcp.srcport', 'tcp.dstport', 'tcp.seq', 'tcp.ack') 19 | if ii == jj && i['tcp.payload'] != j['tcp.payload'] 20 | mots << i['frame.number'] << j['frame.number'] 21 | end 22 | end 23 | 24 | if mots.empty? 25 | puts "No suspicious packets found" 26 | else 27 | puts "Discover suspicious packets: #{mots.size / 2}" 28 | 29 | puts "wireshark display express:" 30 | puts " frame.number in {#{mots.join(' ')}}" 31 | end 32 | -------------------------------------------------------------------------------- /misc/encoder/morese_decode.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # 3 | # Author L 4 | # 5 | 6 | code_map = {".-"=>"A", "-..."=>"B", "-.-."=>"C", "-.."=>"D", "."=>"E", "..-."=>"F", "--."=>"G", "...."=>"H", ".."=>"I", ".---"=>"J", "-.-"=>"K", ".-.."=>"L", "--"=>"M", "-."=>"N", "---"=>"O", ".--."=>"P", "--.-"=>"Q", ".-."=>"R", "..."=>"S", "-"=>"T", "..-"=>"U", "...-"=>"V", ".--"=>"W", "-..-"=>"X", "-.--"=>"Y", "--.."=>"Z", "-----"=>"0", ".----"=>"1", "..---"=>"2", "...--"=>"3", "....-"=>"4", "....."=>"5", "-...."=>"6", "--..."=>"7", "---.."=>"8", "----."=>"9", ".-.-.-"=>".", "--..--"=>",", "..--.."=>"?", ".----."=>"'", "-.-.--"=>"!", "-..-."=>"/", "-.--."=>"(", "-.--.-"=>")", ".-..."=>"&", "---..."=>"=>", "-.-.-."=>";", "-...-"=>"=", ".-.-."=>"+", "-....-"=>"-", "..--.-"=>"_", ".-..-."=>"\"", "...-..-"=>"$", ".--.-."=>"@", "...---..."=>"SOS"} 7 | 8 | code = $<.read.strip 9 | chars = code.chars.uniq - [' '] 10 | abort '[!] Not a Morese Code' unless chars.size == 2 11 | 12 | ok = false 13 | %w( .- -. ).each do |cs| 14 | codes = code.tr(chars.join, cs).split 15 | strs = codes.map(&code_map) 16 | if strs.all? 17 | ok = true 18 | puts "[+] code: #{codes.join(' ')}" 19 | puts strs.join 20 | puts 21 | end 22 | end 23 | 24 | abort '[!] Not a Morese Code' unless ok 25 | -------------------------------------------------------------------------------- /crypto/shiro_rememberMe_decrypt.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # 3 | # Author L 4 | # Shiro rememberMe decrypt 5 | # 6 | 7 | require 'openssl' 8 | 9 | if ARGV.size != 1 or !File.readable?(ARGV[0]) 10 | puts <<~EOF 11 | Usage: ruby shiro_rememberMe_decrypt.rb 12 | 13 | e.g. ruby shiro_rememberMe_decrypt.rb a.txt > /tmp/java_serialization.bin 14 | 15 | EOF 16 | exit 17 | end 18 | cipher = File.binread(ARGV[0]).unpack1 'm' 19 | 20 | Keys = File.readlines("#{__dir__}/shiro_keys.txt", chomp: true) 21 | 22 | def aes_decrypt(mode, key, payload) 23 | iv = payload[0,16] 24 | data = payload[16..-1] 25 | aes = OpenSSL::Cipher.new("aes-128-#{mode}") 26 | 27 | data = data[0...-16] if aes.authenticated? 28 | aes.decrypt 29 | aes.iv_len = 16 if mode == :gcm 30 | aes.iv = iv 31 | aes.key = key.unpack1('m0') 32 | aes.update(data) + (aes.final rescue '') 33 | end 34 | 35 | # require 'pry';binding.pry 36 | mark_head = "\xAC\xED\x00\x05".b 37 | found = false 38 | Keys.each do |key| 39 | [:cbc, :gcm].each do |mode| 40 | plaintext = aes_decrypt(mode, key, cipher) 41 | if (index = plaintext.index(mark_head)) 42 | plaintext = plaintext[index..-1] 43 | STDERR.puts "Mode: #{mode.upcase}, Key: #{key}" 44 | print plaintext 45 | found = true 46 | break 47 | end 48 | rescue => e 49 | STDERR.puts "[!] mode:#{mode} key:#{key}, #{e}" 50 | end 51 | end 52 | STDERR.puts "[!] Key not found" unless found 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CTF Scripts 2 | 3 | ### MISC 4 | ```ruby 5 | compress/ 6 | zipfake.rb -- PKZip 文件伪加密 7 | rarfake.rb -- RAR 文件伪加密 8 | 9 | pcap/ 10 | usbkeyboard.rb -- USB 协议提取键盘输入内容 11 | usbmouse.rb -- USB 协议提取鼠标输入转为图片轨迹图 12 | tsc_tspl_printer.rb -- TSC TSPL 打印机,打印数据图片输出 (目前仅支持BITMAP/BAR) 13 | mots_check.rb -- MOTS 攻击检测 14 | 15 | stego/ 16 | stegosaurus.py -- .py/.pyc/.pyo 的隐写工具 17 | zwsp-steg.rb -- ZWSP 隐写信息编码成不可见字符 (3或5个不可见字符编码) 18 | 19 | encoder/ 20 | base92.rb -- base92 encode/decode 21 | brainfuck.rb -- brainfuck && ook text encode/decode 22 | morese_decode.rb -- 莫斯电码解码 23 | 24 | image/ 25 | png_size_recover.rb -- Png 文件的size恢复 26 | ``` 27 | 28 | ### CRYPTO 29 | ```ruby 30 | weblogic_password.rb -- Weblogic 密码解密脚本 (支持{AES256}) 31 | weblogic_password.py -- 旧版 Weblogic 密码解密脚本 (该版本停止维护; 依赖旧版Cipher) 32 | shiro_rememberMe_decrypt.rb -- Shiro Cookie rememberMe 解密 33 | ``` 34 | 35 | ### AWD 36 | ```ruby 37 | scanner/ 38 | synproxy-scan.rb -- SYN Proxy Scan v2. (不支持Windows 使用) 39 | old-synproxy-scan.py -- SYN Proxy Scan v1. (不建议OSX 使用) 40 | ``` 41 | 42 | ### ICS 43 | ```ruby 44 | pcap/ 45 | ics_analysis.rb -- ICS Protocol Analysis 字段提取统计 46 | tcp_payload_filter.rb -- 过滤TCP Payload 内容 47 | mms_extract_file.rb -- Multimedia Messaging Service 文件提取 48 | asn_to_hash.rb !- .asn 数据转换成 Ruby Hash 49 | ``` 50 | 51 | #### 备注 52 | ```ruby 53 | !- 为工具开发协助脚本 54 | ``` 55 | -------------------------------------------------------------------------------- /misc/image/png_size_recover.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # 3 | # Author L 4 | # png_size_recover.rb image 5 | # 6 | 7 | require 'crc' 8 | 9 | abort "Usage: ./png_size_recover.rb " if ARGV.empty? 10 | 11 | max = 3000 12 | @png_file = ARGV[0] 13 | 14 | data = File.binread(@png_file) 15 | 16 | ihdr_head = data[12,4] 17 | org_width = data[16,4] 18 | org_high = data[20,4] 19 | ihdr_tail = data[24,5] 20 | crc = data[29,4] 21 | 22 | ihdr = ihdr_head + org_width + org_high + ihdr_tail 23 | if CRC.crc32.digest(ihdr) == crc 24 | abort 'No problem with the picture' 25 | end 26 | 27 | 28 | def recover_file(data, values) 29 | values.each do |name, i| 30 | if name == :width 31 | data[16,4] = [i].pack('i>') 32 | else 33 | data[20,4] = [i].pack('i>') 34 | end 35 | puts "[+] recover #{name}: #{i}" 36 | end 37 | 38 | file = "recover_#{@png_file}" 39 | File.binwrite(file, data) 40 | puts "[+] save to: #{file}" 41 | exit() 42 | end 43 | 44 | 45 | max.times do |i| 46 | ihdr = ihdr_head + [i].pack('i>') + org_high + ihdr_tail 47 | recover_file(data, width: i) if CRC.crc32.digest(ihdr) == crc 48 | 49 | ihdr = ihdr_head + org_width + [i].pack('i>') + ihdr_tail 50 | recover_file(data, high: i) if CRC.crc32.digest(ihdr) == crc 51 | end 52 | 53 | (1..max).each do |wi| 54 | width = [wi].pack('i>') 55 | (1..max).each do |hi| 56 | ihdr = ihdr_head + width + [hi].pack('i>') + ihdr_tail 57 | recover_file(data, width: wi, high: hi) if CRC.crc32.digest(ihdr) == crc 58 | end 59 | end 60 | 61 | puts "[!] recover fail" 62 | -------------------------------------------------------------------------------- /misc/compress/zipfake.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # 3 | # Author L 4 | # 5 | require 'zip' 6 | 7 | # bytes_num & 1 为加密位,0为无加密,1为需要加密 8 | class ZipFake 9 | # block_size 10M 10 | def initialize(filename, block_size = 10485760) 11 | @path = filename 12 | @bsize = block_size 13 | @size = File.size(filename) 14 | @mark = "PK\x01\x02" 15 | end 16 | 17 | def lock 18 | # 判断是否文件,仅对文件设置lock, 19 | # 否则会造成ZipFake#unlock无法恢复正常文件 20 | lock_seq = '' 21 | Zip::File.foreach(@path) do |entry| 22 | lock_seq << ( entry.file? ? 1 : 0 ) 23 | end 24 | set_encrypt_bytes(lock_seq) 25 | end 26 | 27 | def unlock 28 | lock_seq = [] 29 | set_encrypt_bytes(lock_seq) 30 | 31 | # "PK\x03\x04\x14\x03\x00\x00\b\x00" 第7位的全局加密解锁 32 | if File.binread(@path, 7).match? /PK\x03\x04..\x01/ 33 | open(@path, 'rb+') do |fio| 34 | fio.seek(6) 35 | fio.putc("\x00") 36 | end 37 | puts "recover zip magic head encryption bit" 38 | end 39 | end 40 | 41 | private 42 | def set_encrypt_bytes(seq) 43 | fio = open(@path, 'rb+') 44 | pos = 0 45 | n = 0 46 | while block = fio.read(@bsize) 47 | if index = block.index(@mark) 48 | offset = (block.size - index - 8) 49 | fio.seek(-offset, IO::SEEK_CUR) 50 | fio.putc(seq[n] || "\x00") 51 | n += 1 52 | elsif fio.pos != @size 53 | fio.seek(-3, IO::SEEK_CUR) 54 | end 55 | end 56 | puts "success #{n} flag(s) found" 57 | ensure 58 | fio.close 59 | end 60 | end 61 | 62 | if __FILE__ == $PROGRAM_NAME 63 | if ARGV.size == 2 64 | abort "No such option '#{ARGV[0]}'" unless 're'.index ARGV[0] 65 | abort "No such file '#{ARGV[1]}'" unless File.exist? ARGV[1] 66 | 67 | zip = ZipFake.new(ARGV[1]) 68 | if ARGV[0] == 'r' 69 | zip.unlock 70 | else 71 | zip.lock 72 | end 73 | else 74 | puts <<~EOF 75 | usage: 76 | zipfake.rb