1
1
use std:: fs;
2
+ use std:: sync:: Arc ;
3
+ use std:: sync:: Mutex ;
2
4
3
5
use base64;
4
6
use hex:: FromHexError ;
@@ -66,35 +68,68 @@ impl Dec {
66
68
}
67
69
}
68
70
71
+ struct PrioQueue ( Arc < Mutex < Vec < u8 > > > ) ;
72
+ impl PrioQueue {
73
+ pub fn new ( init : Vec < u8 > ) -> Self {
74
+ PrioQueue ( Arc :: new ( Mutex :: new ( init) ) )
75
+ }
76
+
77
+ pub fn prio ( & self , byte : u8 ) {
78
+ let mut q = self . 0 . lock ( ) . unwrap ( ) ;
79
+ let i = q. iter ( ) . position ( |b| byte == * b) . unwrap ( ) ;
80
+ q. remove ( i) ;
81
+ q. insert ( 0 , byte) ;
82
+ }
83
+
84
+ pub fn iter ( & self ) -> impl Iterator < Item = u8 > {
85
+ let q = self . 0 . lock ( ) . unwrap ( ) ;
86
+ q. clone ( ) . into_iter ( )
87
+ }
88
+ }
89
+
69
90
type Result < T , E = Error > = std:: result:: Result < T , E > ;
70
91
type DecResult = Result < Dec > ;
71
92
93
+ /*async fn decrypt_pad<'a>(payload: &mut [u8], last: &[u8], oracle: &CmdOracle<'a>) -> Result<u8> {
94
+ let blksz = payload.len() / 2;
95
+ let last_last = last[blksz -1];
96
+ for b in 1..blksz +1 {
97
+ payload[blksz -1] = b as u8 ^ last_last;
98
+ if oracle.request(&payload).await? {
99
+ for i in (blksz -1) - b..blksz {
100
+ payload[
101
+ }
102
+ return Ok(b)
103
+ }
104
+ }
105
+ Err(Error::BraveOracle {})
106
+ }*/
107
+
72
108
async fn decrypt_intermediate < ' a > ( blk : & [ u8 ] ,
73
109
last : & [ u8 ] ,
74
110
oracle : & CmdOracle < ' a > ,
75
- chars : [ u8 ; 256 ] ) -> Result < Vec < u8 > > {
111
+ chars : & PrioQueue ,
112
+ is_last : bool ) -> Result < Vec < u8 > > {
76
113
let blksz = blk. len ( ) ;
77
114
let mut intermediate = vec ! [ 0 ; blksz] ;
78
115
let mut payload = vec ! [ 0 ; blksz * 2 ] ;
79
116
payload[ blksz..] . copy_from_slice ( blk) ;
80
- let mut prio = chars. to_vec ( ) ;
81
117
for i in ( 0 ..blksz) . rev ( ) {
82
118
let pad = ( blksz - i) as u8 ;
83
119
( i +1 ..blksz) . rev ( ) . for_each ( |j| payload[ j] = pad ^ intermediate[ j] ) ;
84
120
85
121
let mut took = 0 ;
86
- // TODO predict based on all last chars
87
- let prio_tmp = prio. to_vec ( ) ;
88
- for ( j, b) in prio_tmp. iter ( ) . enumerate ( ) {
89
- payload[ i] = b ^ ( last[ i] ^ pad) ;
122
+ for ( j, b) in chars. iter ( ) . enumerate ( ) {
123
+ payload[ i] = b ^ ( pad ^ last[ i] ) ;
124
+ println ! ( "guess: {:?} / {}" , std:: str :: from_utf8( & vec![ b] ) , b) ;
90
125
if oracle. request ( & payload) . await ? {
91
- prio . remove ( j ) ;
92
- prio . insert ( 0 , * b) ;
93
- took = j ; break ;
126
+ took = j ;
127
+ chars . prio ( b) ;
128
+ break ;
94
129
}
95
130
}
96
131
println ! ( "oracle took {} tries" , took) ;
97
- ensure ! ( took != chars . len ( ) , BraveOracle ) ;
132
+ ensure ! ( took != 255 , BraveOracle ) ;
98
133
intermediate[ i] = payload[ i] ^ pad;
99
134
}
100
135
@@ -106,11 +141,12 @@ async fn decrypt<'a>(cipher: &[u8],
106
141
oracle : & CmdOracle < ' a > ,
107
142
chars : [ u8 ; 256 ] ) -> Result < Vec < DecResult > > {
108
143
let blocks = cipher. chunks ( blksz) . collect :: < Vec < & [ u8 ] > > ( ) ;
144
+ let chars = PrioQueue :: new ( chars. to_vec ( ) ) ;
109
145
let i = future:: join_all ( blocks
110
146
. iter ( )
111
147
. skip ( 1 )
112
148
. zip ( blocks[ 0 ..blocks. len ( ) -1 ] . iter ( ) )
113
- . map ( |( blk1, blk2) | decrypt_intermediate ( blk1, blk2, oracle, chars) ) )
149
+ . map ( |( blk1, blk2) | decrypt_intermediate ( blk1, blk2, oracle, & chars, blk1 == blocks . last ( ) . unwrap ( ) ) ) )
114
150
. await ;
115
151
116
152
Ok ( blocks
@@ -149,7 +185,7 @@ async fn main() {
149
185
. help ( "CBC block size" ) )
150
186
. arg ( Arg :: with_name ( "chars" )
151
187
. long ( "chars" ) . takes_value ( true ) . default_value ( "english.chars" )
152
- . long_help ( concat ! ( "space seperated list of hex encoded bytes to guess the plaintext. " ,
188
+ . long_help ( concat ! ( "( space seperated) list of hex encoded bytes to guess the plaintext. " ,
153
189
"ALL 256 POSSIBLE BYTES MUST BE PRESENT in no particular order. " ,
154
190
"example: 00 01 02 ... 61 62 63 ... 6A 6B ... FF FF" ) ) )
155
191
. arg ( Arg :: with_name ( "oracle" )
0 commit comments