diff --git a/.gitignore b/.gitignore
index 177cc3a..918d083 100755
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
 /target
 /src/dma/cs2dumper/offsets_mod.rs
 /src/dma/cs2dumper/client_mod.rs
-/src/dma/cs2dumper/engine2_mod.rs
\ No newline at end of file
+/src/dma/cs2dumper/engine2_mod.rs
+dump.sh
diff --git a/src/cli.rs b/src/cli.rs
index 3d83ab6..9106c89 100755
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -6,7 +6,7 @@ use memflow::plugins::Inventory;
 use crate::dma::Connector;
 const PORT_RANGE: std::ops::RangeInclusive<usize> = 8000..=65535;
 
-#[derive(Parser)]
+#[derive(Parser, Clone)]
 #[command(author, version = version(), about, long_about = None)]
 pub struct Cli {
     /// Specifies the connector type for DMA
diff --git a/src/comms.rs b/src/comms.rs
index 8a9a90c..90ea0b0 100755
--- a/src/comms.rs
+++ b/src/comms.rs
@@ -51,6 +51,20 @@ pub enum EntityData {
     Bomb(BombData)
 }
 
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct CheatOptions {
+    #[serde(rename = "revealMoney")]
+    pub reveal_money: bool,
+}
+
+impl Default for CheatOptions {
+    fn default() -> Self {
+        Self {
+            reveal_money: false,
+        }
+    }
+}
+
 #[derive(Debug, Clone, Serialize, Deserialize)]
 pub struct RadarData {
     freq: usize,
@@ -83,13 +97,30 @@ pub struct RadarData {
     #[serde(rename(serialize = "entityData"))]
     player_data: Vec<EntityData>,
 
-    //#[serde(rename(serialize = "localYaw"))]
-    //local_yaw: f32,
+    #[serde(rename = "options")]
+    options: CheatOptions,
+
+    #[serde(skip)]
+    pub money_reveal_enabled: bool,
 }
 
 impl RadarData {
     pub fn new(ingame: bool, map_name: String, player_data: Vec<EntityData>, freq: usize, bomb_planted: bool, bomb_cannot_defuse: bool, bomb_defuse_timeleft: f32, bomb_exploded: bool, bomb_being_defused: bool, bomb_defuse_length: f32, bomb_defuse_end: f32) -> RadarData {
-        RadarData { ingame, map_name, player_data, freq, bomb_planted, bomb_can_defuse: bomb_cannot_defuse, bomb_defuse_timeleft, bomb_exploded, bomb_being_defused, bomb_defuse_length, bomb_defuse_end }
+        RadarData {
+            ingame,
+            map_name,
+            player_data,
+            freq,
+            bomb_planted,
+            bomb_can_defuse: bomb_cannot_defuse,
+            bomb_defuse_timeleft,
+            bomb_exploded,
+            bomb_being_defused,
+            bomb_defuse_length,
+            bomb_defuse_end,
+            options: CheatOptions::default(),
+            money_reveal_enabled: false
+        }
     }
 
     /// Returns empty RadarData, it's also the same data that gets sent to clients when not ingame
@@ -105,9 +136,20 @@ impl RadarData {
             bomb_exploded: false,
             bomb_being_defused: false,
             bomb_defuse_length: 0.0,
-            bomb_defuse_end: 0.0
+            bomb_defuse_end: 0.0,
+            options: CheatOptions::default(),
+            money_reveal_enabled: false
         }
     }
+
+    pub fn set_reveal_money(&mut self, value: bool) {
+        self.options.reveal_money = value;
+        self.money_reveal_enabled = value;
+    }
+
+    pub fn get_reveal_money(&self) -> bool {
+        self.options.reveal_money
+    }
 }
 
 unsafe impl Send for RadarData {}
diff --git a/src/dma/mod.rs b/src/dma/mod.rs
index c23e670..7e4bc42 100755
--- a/src/dma/mod.rs
+++ b/src/dma/mod.rs
@@ -4,17 +4,28 @@ use memflow::{mem::MemoryView, os::Process, types::Address};
 
 use crate::{enums::PlayerType, comms::{EntityData, PlayerData, RadarData, ArcRwlockRadarData, BombData}};
 
+use crate::money_reveal::MoneyReveal;
+
 use self::{context::DmaCtx, threaddata::CsData};
 
-mod context;
-mod threaddata;
+pub mod context;
+pub mod threaddata;
 mod cs2dumper;
 
 pub use context::Connector;
 
 pub async fn run(radar_data: ArcRwlockRadarData, connector: Connector, pcileech_device: String, skip_version: bool) -> anyhow::Result<()> {
     let mut ctx = DmaCtx::setup(connector, pcileech_device, skip_version)?;
-    let mut data = CsData { recheck_bomb_holder: true, ..Default::default() };
+    let mut data = CsData {
+        recheck_bomb_holder: true,
+        money_reveal_enabled: false,
+        ..Default::default()
+    };
+
+    let mut money_reveal = MoneyReveal::new();
+    if let Err(e) = money_reveal.init(&mut ctx.process, &ctx.client_module) {
+        log::warn!("Failed to initialize money reveal: {}", e);
+    }
     
     // For read timing
     let mut last_bomb_dropped = false;
@@ -47,6 +58,17 @@ pub async fn run(radar_data: ArcRwlockRadarData, connector: Connector, pcileech_
 
         data.update_common(&mut ctx);
 
+        {
+            let radar = radar_data.read().await;
+            if radar.money_reveal_enabled != data.money_reveal_enabled {
+                data.money_reveal_enabled = radar.money_reveal_enabled;
+
+                if let Err(e) = money_reveal.toggle(&mut ctx.process) {
+                    log::warn!("Failed to toggle money reveal: {}", e);
+                }
+            }
+        }
+
         // Bomb update
         if (data.bomb_dropped && !last_bomb_dropped) || (data.bomb_planted && !last_bomb_planted) {
             data.update_bomb(&mut ctx);
@@ -247,9 +269,12 @@ pub async fn run(radar_data: ArcRwlockRadarData, connector: Connector, pcileech_
                 data.bomb_defuse_length,
                 bomb_defuse_end
             );
+
+            radar.money_reveal_enabled = data.money_reveal_enabled;
         } else {
             let mut radar = radar_data.write().await;
             *radar = RadarData::empty(freq);
+            radar.money_reveal_enabled = data.money_reveal_enabled;
         }
 
         last_tick_count = data.tick_count;
@@ -264,5 +289,10 @@ pub async fn run(radar_data: ArcRwlockRadarData, connector: Connector, pcileech_
         thread::sleep(Duration::from_millis(1));
     }
 
+    let cleanup_result = money_reveal.ensure_disabled(&mut ctx.process);
+    if let Err(e) = cleanup_result {
+        log::warn!("Failed to cleanup money reveal: {}", e);
+    }
+
     Ok(())
 }
\ No newline at end of file
diff --git a/src/dma/threaddata/mod.rs b/src/dma/threaddata/mod.rs
index f214d18..76640fb 100755
--- a/src/dma/threaddata/mod.rs
+++ b/src/dma/threaddata/mod.rs
@@ -38,6 +38,7 @@ pub struct CsData {
     pub bomb_defuse_length: f32,
     pub bomb_exploded: bool,
     pub bomb_defused: bool,
+    pub money_reveal_enabled: bool,
 }
 
 
diff --git a/src/main.rs b/src/main.rs
index 2d9619b..397e886 100755
--- a/src/main.rs
+++ b/src/main.rs
@@ -13,6 +13,9 @@ mod comms;
 mod dma;
 mod websocket;
 
+mod pattern;
+mod money_reveal;
+
 #[tokio::main]
 async fn main() -> anyhow::Result<()> {
     let cli: Cli = Cli::parse();
@@ -29,6 +32,7 @@ async fn main() -> anyhow::Result<()> {
     );
 
     let radar_clone = radar_data.clone();
+
     let dma_handle = tokio::spawn(async move {
         if let Err(err) = dma::run(radar_clone, cli.connector, cli.pcileech_device, cli.skip_version).await {
             log::error!("Error in dma thread: [{}]", err.to_string());
@@ -37,20 +41,23 @@ async fn main() -> anyhow::Result<()> {
         }
     });
 
+    let web_path = cli.web_path.clone();
+    let port = cli.port;
+
     let _websocket_handle = tokio::spawn(async move {
         if let Ok(my_local_ip) = local_ip_address::local_ip() {
-            let address = format!("http://{}:{}", my_local_ip, cli.port);
+            let address = format!("http://{}:{}", my_local_ip, port);
             println!("Launched webserver at {}", address);
         } else {
-            let address = format!("http://0.0.0.0:{}", cli.port);
+            let address = format!("http://0.0.0.0:{}", port);
             println!("launched webserver at {}", address);
         }
 
-        if let Err(err) = websocket::run(cli.web_path, cli.port, radar_data).await {
+        if let Err(err) = websocket::run(web_path, port, radar_data).await {
             log::error!("Error in ws server: [{}]", err.to_string());
         }
     });
 
     dma_handle.await?;
     Ok(())
-}
+}
\ No newline at end of file
diff --git a/src/money_reveal.rs b/src/money_reveal.rs
new file mode 100644
index 0000000..db85dec
--- /dev/null
+++ b/src/money_reveal.rs
@@ -0,0 +1,96 @@
+use memflow::{mem::MemoryView, types::Address, os::ModuleInfo};
+use crate::pattern::pattern_scan;
+
+const BUF_SIZE: usize = 3;
+
+pub struct MoneyReveal {
+    pub is_enabled: bool,
+    pub address: Option<Address>,
+    original_bytes: Option<[u8; BUF_SIZE]>,
+}
+
+impl MoneyReveal {
+    pub fn new() -> Self {
+        Self {
+            is_enabled: false,
+            address: None,
+            original_bytes: None,
+        }
+    }
+
+    pub fn init(&mut self, mem: &mut impl MemoryView, client_module: &ModuleInfo) -> anyhow::Result<()> {
+        self.address = self.find_function(mem, client_module)?;
+        log::info!("Money reveal function found at: {:?}", self.address);
+        Ok(())
+    }
+
+    pub fn toggle(&mut self, mem: &mut impl MemoryView) -> anyhow::Result<bool> {
+        if let Some(addr) = self.address {
+            if self.is_enabled {
+                if let Some(original) = self.original_bytes {
+                    self.restore(mem, addr, original)?;
+                    self.original_bytes = None;
+                    self.is_enabled = false;
+                }
+            } else {
+                let original = self.patch(mem, addr)?;
+                self.original_bytes = Some(original);
+                self.is_enabled = true;
+            }
+            Ok(self.is_enabled)
+        } else {
+            Err(anyhow::anyhow!("Money reveal not initialized"))
+        }
+    }
+
+    pub fn ensure_disabled(&mut self, mem: &mut impl MemoryView) -> anyhow::Result<()> {
+        if self.is_enabled {
+            if let Some(addr) = self.address {
+                if let Some(original) = self.original_bytes {
+                    self.restore(mem, addr, original)?;
+                    self.is_enabled = false;
+                }
+            }
+        }
+        Ok(())
+    }
+
+    fn find_function(&self, mem: &mut impl MemoryView, module: &ModuleInfo) -> anyhow::Result<Option<Address>> {
+        let is_hltv = pattern_scan(
+            mem,
+            module,
+            "48 83 EC 28 48 8B 0D ?? ?? ?? ?? 48 8B 01 FF 90 ?? ?? ?? ?? 84 C0 75 0D"
+        )?;
+
+        if is_hltv.is_none() {
+            Ok(pattern_scan(
+                mem,
+                module,
+                "B0 01 C3 28 48 8B 0D ?? ?? ?? ?? 48 8B 01 FF 90 ?? ?? ?? ?? 84 C0 75 0D"
+            )?)
+        } else {
+            Ok(is_hltv)
+        }
+    }
+
+    fn patch(&self, mem: &mut impl MemoryView, location: Address) -> anyhow::Result<[u8; BUF_SIZE]> {
+        let mut original_buf = [0u8; BUF_SIZE];
+        mem.read_into(location, &mut original_buf)?;
+
+        let new_buf: [u8; BUF_SIZE] = [
+            0xB0, 0x01,     // MOV AL,1
+            0xC3            // RET
+        ];
+
+        log::debug!("Patching memory for money reveal");
+        mem.write(location, &new_buf)?;
+
+        Ok(original_buf)
+    }
+
+    fn restore(&self, mem: &mut impl MemoryView, location: Address, original: [u8; BUF_SIZE]) -> anyhow::Result<()> {
+        log::debug!("Restoring memory for money reveal");
+        mem.write(location, &original)?;
+        Ok(())
+    }
+}
\ No newline at end of file
diff --git a/src/pattern.rs b/src/pattern.rs
new file mode 100644
index 0000000..c85d7f0
--- /dev/null
+++ b/src/pattern.rs
@@ -0,0 +1,51 @@
+use std::io::Read;
+use log::warn;
+use memflow::{os::ModuleInfo, mem::MemoryView, types::Address};
+
+fn pattern_to_bytes(pattern: String) -> Vec<Option<u8>> {
+    pattern.split(' ')
+        .fold(Vec::new(), |mut accum, str| {
+            if str == "??" {
+                accum.push(None);
+            } else {
+                let byte = u8::from_str_radix(str, 16).unwrap();
+                accum.push(Some(byte));
+            }
+
+            accum
+        })
+}
+
+pub fn pattern_scan(mem: &mut impl MemoryView, module: &ModuleInfo, sig: &str) -> anyhow::Result<Option<Address>> {
+    let pattern_bytes = pattern_to_bytes(sig.to_owned());
+    let mut cursor = mem.cursor();
+
+    log::debug!("Searching \"{}\" for pattern: \"{}\"", module.name, sig);
+
+    for i in 0..module.size {
+        let mut found = true;
+        cursor.set_address(module.base + i);
+
+        let mut buf = vec![0u8; pattern_bytes.len()];
+
+        if let Err(_) = cursor.read(&mut buf) {
+            warn!("Encountered read error while scanning for pattern");
+            continue;
+        }
+
+        for (idx, byte) in buf.iter().enumerate() {
+            if let Some(pat_byte) = pattern_bytes[idx] {
+                if *byte != pat_byte {
+                    found = false;
+                    break;
+                }
+            }
+        }
+
+        if found {
+            return Ok(Some(module.base + i));
+        }
+    }
+
+    Ok(None)
+}
\ No newline at end of file
diff --git a/src/websocket.rs b/src/websocket.rs
index 46a9e97..b4fd054 100644
--- a/src/websocket.rs
+++ b/src/websocket.rs
@@ -25,29 +25,43 @@ async fn ws_handler(ws: WebSocketUpgrade, State(state): State<AppState>) -> Resp
 async fn handle_socket(mut socket: WebSocket, state: AppState) {
     while let Some(msg) = socket.recv().await {
         if let Ok(msg) = msg {
-            if msg == Message::Text("requestInfo".to_string()) {
-                let str = {
-                    let data = state.data_lock.read().await;
+            if let Ok(text) = msg.to_text() {
+                if text == "requestInfo" {
+                    let str = {
+                        let data = state.data_lock.read().await;
 
-                    match serde_json::to_string(&*data) {
-                        Ok(json) => json,
-                        Err(e) => {
-                            log::error!("Could not serialize data into json: {}", e.to_string());
-                            log::error!("Sending \"error\" instead");
-                            "error".to_string()
-                        },
+                        match serde_json::to_string(&*data) {
+                            Ok(json) => json,
+                            Err(e) => {
+                                log::error!("Could not serialize data into json: {}", e.to_string());
+                                log::error!("Sending \"error\" instead");
+                                "error".to_string()
+                            },
+                        }
+                    };
+
+                    if socket.send(Message::Text(str)).await.is_err() {
+                        return;
                     }
-                };
+                } else if text == "toggleMoneyReveal" {
+                    let new_value = {
+                        let mut data = state.data_lock.write().await;
+                        data.money_reveal_enabled = !data.money_reveal_enabled;
+                        data.money_reveal_enabled
+                    };
 
-                //println!("{str}");
+                    let response = serde_json::json!({
+                        "action": "toggleMoneyReveal",
+                        "status": "success",
+                        "enabled": new_value
+                    });
 
-                if socket.send(Message::Text(str)).await.is_err() {
-                    // client disconnected
-                    return;
+                    if socket.send(Message::Text(response.to_string())).await.is_err() {
+                        return;
+                    }
                 }
             }
         } else {
-            // client disconnected
             return;
         }
     }
diff --git a/webradar/index.html b/webradar/index.html
index 5729dd9..e847d08 100644
--- a/webradar/index.html
+++ b/webradar/index.html
@@ -26,6 +26,10 @@
                     <input type="checkbox" onclick="toggleGuns()" id="gunsCheck" name="guns"/>
                     <label for="gunsCheck">Weapons</label>
                 </div>
+                <div>
+                    <input type="checkbox" onclick="toggleMoneyReveal()" id="moneyReveal" name="money"/>
+                    <label for="moneyReveal">Money Reveal (DANGEROUS!)</label>
+                </div>
             </div>
         </div>
         <canvas id="canvas"></canvas>
diff --git a/webradar/script.js b/webradar/script.js
index 5eba57c..a1b7a6c 100644
--- a/webradar/script.js
+++ b/webradar/script.js
@@ -652,28 +652,36 @@ function connect() {
             if (event.data == "error") {
                 console.log("[radarflow] Server had an unknown error")
             } else {
-                let data = JSON.parse(event.data);
-                radarData = data;
-                freq = data.freq;
+                try {
+                    let data = JSON.parse(event.data);
+                    radarData = data;
+                    freq = data.freq;
 
-                if (data.ingame == false) {
-                    mapName = null
-                    entityData = null
-
-                    if (loaded)
-                        unloadMap()
-                } else {
-                    if (!loaded) {
-                        mapName = data.mapName
-                        entityData = data.entityData
-                        loadMap(mapName)
-                    } else {
-                        entityData = data.entityData
+                    if (data.money_reveal_enabled !== undefined) {
+                        document.getElementById("moneyReveal").checked = data.money_reveal_enabled;
                     }
-                }
 
-                update = true
-                requestAnimationFrame(render);
+                    if (data.ingame == false) {
+                        mapName = null
+                        entityData = null
+
+                        if (loaded)
+                            unloadMap()
+                    } else {
+                        if (!loaded) {
+                            mapName = data.mapName
+                            entityData = data.entityData
+                            loadMap(mapName)
+                        } else {
+                            entityData = data.entityData
+                        }
+                    }
+
+                    update = true
+                    requestAnimationFrame(render);
+                } catch (e) {
+                    console.error("[radarflow] Error parsing server message:", e, event.data);
+                }
             }
         };
 
@@ -710,6 +718,7 @@ addEventListener("DOMContentLoaded", (e) => {
     document.getElementById("statsCheck").checked = true;
     document.getElementById("namesCheck").checked = true;
     document.getElementById("gunsCheck").checked = true;
+    document.getElementById("moneyReveal").checked = false;
 
     canvas = document.getElementById('canvas');
     canvas.width = 1024;
@@ -735,4 +744,10 @@ function toggleNames() {
 
 function toggleGuns() {
     drawGuns = !drawGuns
+}
+
+function toggleMoneyReveal() {
+    if (websocket && websocket.readyState === WebSocket.OPEN) {
+        websocket.send("toggleMoneyReveal");
+    }
 }
\ No newline at end of file