Padding Oracle Attack

前段时间打的某个ctf里遇到的...由于一些小问题当时并没有做出来...

只是表述一下思路

下文的0x00 == '\x00', 以此类推

#!/usr/bin/ruby
require "base64"
require "..."

/*
  A demo for AES CBC Padding Oracle Attack
  author: Minty_He
*/

LENGTH = 16
origin_iv = "AAAAAAAAAAAAAAAA" //初始iv
flag = Base64.decode64("flag") //密文

/*  
	...
	...
	cchunk1 = flag[0..15]
	cchunk2 = flag[16..31]
	将密文分块 
	16个为一块
	...
	...
*/ 

def get_result(iv, chunk)
  cipher = chunk
  // 使用cipher和当前iv调用nc
  result = file.readline
  // result是通过nc获取到的解密成功与否的结果
  // 如果返回结果为"Decrpytion Done" 说明解密成功,函数返回true
  return true or false
end

def get_plaintext(origin_iv, chunk)
/*
  主要逻辑部分:
  从最后一位开始从右向左遍历整个块
  通过get_result返回的值猜测当前位iv(从0~255)
  如果猜测成功,当前位iv xor 0xpos xor 当前位原iv 结果即为当前位的明文
*/
  plaintext = 0x00 * LENGTH //储存明文
  mid = 0x00 * LENGTH //mid储存经过aes key解密后还未与iv进行xor运算的中间值
   //从块末往前遍历,pos表示在跑当前块的倒数第几位
  for pos in 1..16
    string = 0x00 * (length - pos) + (0xpos * pos) 
    /*
	  string就是我们构造出来的明文
	  string的构造为0x000000.......pos
	  如果pos为1,string即为0x000000......01
	  如果pos为2,string即为0x000000....0202
	  依此类推
    */
    //开始爆破iv
    for char in 0..255
      iv = 0x00 * (length - pos) + 0xchar + (mid[(length - pos + 1)..15] xor (0xpos * (pos - 1))) //这里需要检查是否越界,越界返回空字符串
	  if get_result(iv, chunk)
	    mid[length - pos] = iv[length - pos] xor 0xpos
	    plaintext[length - pos] = mid[length - pos] xor origin_iv[length - pos]
	    break
      end
    end
  return plaintext
end

plaintext = get_plaintext(origin_iv, cchunk1) + get_plaintext(cchunk1, cchunk2) +
			get_plaintext(cchunk2, cchunk3) + get_plaintext(cchunk3, cchunk4) +
			.......................................................................
  
  
  
 

附上题目:

#!/usr/bin/ruby -w
require 'openssl'
require 'base64'

def banner()
    puts ' ____________________________________________'
    puts '|                                            |'
    puts '| Welcome to our secure communication system |'
    puts '| Our system is secured by AES               |'    
    puts '| So...No key! No Message!                   |'
    puts '|____________________________________________|'
    puts ''
end

def option()
    puts '1. Get the secret message.'
    puts '2. Encrypt the message'
    puts '3. Decrypt the message.'
    puts 'Give your option:'
    STDOUT.flush
    op=gets
    return op.to_i
end

def init()
    file_key=File.new("./aeskey","r")
    $key=file_key.gets
    file_key.close()
end
def aes_encrypt(iv,data)
    cipher = OpenSSL::Cipher::AES.new(256, :CBC)
    cipher.encrypt
    cipher.key = $key
    cipher.iv  = iv
    cipher.update(data) << cipher.final
end

def aes_decrypt(iv,data)
    cipher = OpenSSL::Cipher::AES.new(256, :CBC)
    cipher.decrypt
    cipher.key = $key
    cipher.iv  = iv
    data = cipher.update(data) << cipher.final
end

def output_secret()
    file_secret=File.new("./flag","r")
    secret=file_secret.gets
    file_secret.close
    secret_enc=aes_encrypt("A"*16,secret)
    secret_enc_b64=Base64.encode64(secret_enc)
    puts secret_enc_b64 
end

init
banner
while true do
    begin
        op=option
        if op==1
            output_secret
        elsif op==2
            puts "IV:"
            STDOUT.flush
            iv=Base64.decode64(gets)
            puts "Data:"
            STDOUT.flush
            data=Base64.decode64(gets)
            data_enc=aes_encrypt iv,data
            puts Base64.encode64(data_enc)
            puts "Encrytion Done"    
            STDOUT.flush
        elsif op==3
            puts "IV:"
            STDOUT.flush
            iv=Base64.decode64(gets)
            puts "Data:"
            STDOUT.flush
            data=Base64.decode64(gets)
            data_dec=aes_decrypt iv,data
            puts "Decrpytion Done"
            STDOUT.flush
        else
            puts 'Wrong Option'
            STDOUT.flush
        end
    rescue Exception => e  
        puts e.message
        STDOUT.flush
        retry
    end
end

点击右边的按钮加载评论,如果无法加载那估计是被墙啦..你看着办w