Your locally hosted lumina server for IDAPro
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add IDA8.1 support (#42)

* wip: print dumps for new protocol version

* only allow 'guest' to connect for now (ida 8.1+)

* bump version to v0.2.0

authored by

Naim A and committed by
GitHub
8b78d0a7 7f0d4e6a

+54 -17
+6 -6
Cargo.lock
··· 102 102 103 103 [[package]] 104 104 name = "clap" 105 - version = "4.0.12" 105 + version = "4.0.13" 106 106 source = "registry+https://github.com/rust-lang/crates.io-index" 107 - checksum = "385007cbbed899260395a4107435fead4cad80684461b3cc78238bdcb0bad58f" 107 + checksum = "69d64e88428747154bd8bc378d178377ef4dace7a5735ca1f3855be72f2c2cb5" 108 108 dependencies = [ 109 109 "atty", 110 110 "bitflags", ··· 124 124 125 125 [[package]] 126 126 name = "common" 127 - version = "0.1.0" 127 + version = "0.2.0" 128 128 dependencies = [ 129 129 "binascii", 130 130 "futures-util", ··· 555 555 556 556 [[package]] 557 557 name = "lumen" 558 - version = "0.1.0" 558 + version = "0.2.0" 559 559 dependencies = [ 560 560 "clap", 561 561 "common", ··· 1285 1285 1286 1286 [[package]] 1287 1287 name = "tokio-stream" 1288 - version = "0.1.10" 1288 + version = "0.1.11" 1289 1289 source = "registry+https://github.com/rust-lang/crates.io-index" 1290 - checksum = "f6edf2d6bc038a43d31353570e27270603f4648d18f5ed10c0e179abe43255af" 1290 + checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" 1291 1291 dependencies = [ 1292 1292 "futures-core", 1293 1293 "pin-project-lite",
+1 -1
common/Cargo.toml
··· 1 1 [package] 2 2 name = "common" 3 3 description = "common utilities for lumen" 4 - version = "0.1.0" 4 + version = "0.2.0" 5 5 authors = ["Naim A. <naim@abda.nl>"] 6 6 edition = "2018" 7 7 publish = false
+7 -1
common/src/rpc/messages.rs
··· 13 13 pub msg: &'a str, 14 14 } 15 15 16 + #[derive(Serialize, Deserialize, Debug)] 17 + pub struct Creds<'a> { 18 + pub username: &'a str, 19 + pub password: &'a str, 20 + } 21 + 16 22 #[derive(Serialize, Deserialize)] 17 23 pub struct RpcHello<'a> { 18 - pub unk0: u32, 24 + pub protocol_version: u32, 19 25 pub license_data: &'a [u8], 20 26 pub lic_number: [u8; 6], 21 27 pub unk2: u32,
+23 -6
common/src/rpc/mod.rs
··· 117 117 Ok(()), 118 118 Fail(RpcFail<'a>), 119 119 Notify(RpcNotify<'a>), 120 - Hello(RpcHello<'a>), 120 + Hello(RpcHello<'a>, Option<Creds<'a>>), 121 121 PullMetadata(PullMetadata<'a>), 122 122 PullMetadataResult(PullMetadataResult<'a>), 123 123 PushMetadata(PushMetadata<'a>), ··· 138 138 RpcMessage::Ok(msg) => tuple.serialize_element(msg)?, 139 139 RpcMessage::Fail(msg) => tuple.serialize_element(msg)?, 140 140 RpcMessage::Notify(msg) => tuple.serialize_element(msg)?, 141 - RpcMessage::Hello(msg) => tuple.serialize_element(msg)?, 141 + RpcMessage::Hello(msg, _) => tuple.serialize_element(msg)?, 142 142 RpcMessage::PullMetadata(msg) => tuple.serialize_element(msg)?, 143 143 RpcMessage::PullMetadataResult(msg) => tuple.serialize_element(msg)?, 144 144 RpcMessage::PushMetadata(msg) => tuple.serialize_element(msg)?, ··· 153 153 fn deserialize_check<T: serde::Deserialize<'a>>(payload: &'a [u8]) -> Result<T, Error> { 154 154 let v = de::from_slice(payload)?; 155 155 if v.1 != payload.len() { 156 - trace!("{} remaining bytes after deserializing {}", payload.len() - v.1, std::any::type_name::<T>()); 156 + let bytes_remaining = crate::make_pretty_hex(&payload[v.1..]); 157 + trace!("{} remaining bytes after deserializing {}\n{bytes_remaining}", payload.len() - v.1, std::any::type_name::<T>()); 157 158 } 158 159 Ok(v.0) 159 160 } ··· 165 166 let res = match msg_type { 166 167 0x0a => { 167 168 if !payload.is_empty() { 168 - trace!("Ok message with additional data: {} bytes", payload.len()); 169 + trace!("Ok message with additional data: {} bytes: {payload:02x?}", payload.len()); 169 170 } 170 171 RpcMessage::Ok(()) 171 172 }, 172 173 0x0b => RpcMessage::Fail(Self::deserialize_check(payload)?), 173 174 0x0c => RpcMessage::Notify(Self::deserialize_check(payload)?), 174 - 0x0d => RpcMessage::Hello(Self::deserialize_check(payload)?), 175 + 0x0d => { 176 + let (hello, consumed) = de::from_slice::<messages::RpcHello>(payload)?; 177 + let creds = if payload.len() > consumed && hello.protocol_version > 2 { 178 + let payload = &payload[consumed..]; 179 + let (creds, consumed) = de::from_slice::<Creds>(payload)?; 180 + if payload.len() != consumed { 181 + trace!("bytes remaining after HelloV2: {payload:02x?}"); 182 + } 183 + Some(creds) 184 + } else { 185 + if hello.protocol_version > 2 || payload.len() != consumed { 186 + trace!("Unexpected Hello msg: {payload:02x?}"); 187 + } 188 + None 189 + }; 190 + RpcMessage::Hello(hello, creds) 191 + }, 175 192 0x0e => RpcMessage::PullMetadata(Self::deserialize_check(payload)?), 176 193 0x0f => RpcMessage::PullMetadataResult(Self::deserialize_check(payload)?), 177 194 0x10 => RpcMessage::PushMetadata(Self::deserialize_check(payload)?), ··· 201 218 Ok(_) => 0x0a, 202 219 Fail(_) => 0x0b, 203 220 Notify(_) => 0x0c, 204 - Hello(_) => 0x0d, 221 + Hello(..) => 0x0d, 205 222 PullMetadata(_) => 0x0e, 206 223 PullMetadataResult(_) => 0x0f, 207 224 PushMetadata(_) => 0x10,
+1 -1
lumen/Cargo.toml
··· 1 1 [package] 2 2 name = "lumen" 3 3 description = "lumen server" 4 - version = "0.1.0" 4 + version = "0.2.0" 5 5 authors = ["Naim A. <naim@abda.nl>"] 6 6 edition = "2018" 7 7 publish = false
+16 -2
lumen/src/main.rs
··· 148 148 }, 149 149 }; 150 150 151 - let hello = match RpcMessage::deserialize(&hello) { 152 - Ok(RpcMessage::Hello(v)) => v, 151 + let (hello, creds) = match RpcMessage::deserialize(&hello) { 152 + Ok(RpcMessage::Hello(v, creds)) => { 153 + debug!("hello protocol={}, login creds: {creds:?}", v.protocol_version); 154 + (v, creds) 155 + }, 153 156 _ => { 154 157 // send error 155 158 error!("got bad hello message"); ··· 161 164 return Ok(()); 162 165 } 163 166 }; 167 + 168 + if let Some(ref creds) = creds { 169 + if creds.username != "guest" { 170 + // Only allow "guest" to connect for now. 171 + rpc::RpcMessage::Fail(rpc::RpcFail { 172 + code: 1, 173 + message: &format!("{server_name}: invalid username or password. Try logging in with `guest` instead."), 174 + }).async_write(&mut stream).await?; 175 + return Ok(()); 176 + } 177 + } 164 178 165 179 let resp = rpc::RpcMessage::Ok(()); 166 180 resp.async_write(&mut stream).await?;