Skip to content

Commit

Permalink
Merge pull request #703 from bytedance/feat-nodejs-mem
Browse files Browse the repository at this point in the history
feat nodejs inject mem
  • Loading branch information
yoloyyh authored Nov 6, 2024
2 parents c036b4f + de75b81 commit c33aafa
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 43 deletions.
2 changes: 1 addition & 1 deletion rasp/librasp/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,7 @@ impl RASPManager {
.exe_path
.clone()
.ok_or(anyhow!("process exe path not found: {}", pid))?;
let inspect_port = get_inspect_port(pid);
let inspect_port = get_inspect_port(&process_info);
if inspect_port != 0 {
match nodejs_attach(pid, &environ, &process_exe_file, Some(inspect_port)) {
Ok(result) => {Ok(result)}
Expand Down
113 changes: 71 additions & 42 deletions rasp/librasp/src/nodejs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ use anyhow::{anyhow, Result};
use log::*;
use regex::Regex;
use wait_timeout::ChildExt;
use std::fs::File;
use std::io::BufReader;
use std::io::BufRead;

const NODEJS_INSPECT_PORT_MIN:u16 = 19230;
const NODEJS_INSPECT_PORT_MAX:u16 = 19235;
Expand Down Expand Up @@ -42,23 +45,30 @@ fn parse_port_from_address(address: &str) -> Option<u16> {
}

pub fn get_process_listening_port(pid: i32) -> u16 {
let tcp_path = format!("/proc/{}/net/tcp", pid);

// frist get ipv4 listen port
if let Ok(content) = std::fs::read_to_string(tcp_path) {

for line in content.lines().skip(1) {
let parts: Vec<&str> = line.split_whitespace().collect();
if parts.len() >= 3 {
let local_address = parts[1];
let status = parts[3];
let file_path = format!("/proc/{}/net/tcp", pid);
let file = match File::open(&file_path) {
Ok(f) => f,
Err(_) => return 0,
};
let reader = BufReader::new(file);

for line in reader.lines().skip(1) {
let line = match line {
Ok(l) => l,
Err(_) => return 0,
};
let parts: Vec<&str> = line.split_whitespace().collect();
if parts.len() >= 4 {
let local_address = parts[1];

if status == "0A" {
if let Some(port) = parse_port_from_address(local_address) {
if (NODEJS_INSPECT_PORT_MIN..= NODEJS_INSPECT_PORT_MAX).contains(&port) {
info!("Found IPv4 listen port {} for pid {}", port, pid);
return port;
}
let status = parts[3];
if status == "0A" {
if let Some(port) = parse_port_from_address(local_address) {
if (NODEJS_INSPECT_PORT_MIN..= NODEJS_INSPECT_PORT_MAX).contains(&port) {
info!("Found IPv4 listen port {} for pid {}", port, pid);
return port;
}
}
}
Expand All @@ -67,20 +77,26 @@ pub fn get_process_listening_port(pid: i32) -> u16 {

// get ipv6 listen port
let tcp6_path = format!("/proc/{}/net/tcp6", pid);
if let Ok(content) = std::fs::read_to_string(tcp6_path) {

for line in content.lines().skip(1) {
let parts: Vec<&str> = line.split_whitespace().collect();
if parts.len() >= 3 {
let local_address = parts[1];
let status = parts[3];
let file = match File::open(&tcp6_path) {
Ok(f) => f,
Err(_) => return 0,
};
let reader = BufReader::new(file);
for line in reader.lines().skip(1) {
let line = match line {
Ok(l) => l,
Err(_) => return 0,
};
let parts: Vec<&str> = line.split_whitespace().collect();
if parts.len() >= 4 {
let local_address = parts[1];
let status = parts[3];

if status == "0A" {
if let Some(port) = parse_port_from_address(local_address) {
if (16680..= NODEJS_INSPECT_PORT_MAX).contains(&port) {
info!("Found IPv6 listen port {} for pid {}", port, pid);
return port;
}
if status == "0A" {
if let Some(port) = parse_port_from_address(local_address) {
if (NODEJS_INSPECT_PORT_MIN..= NODEJS_INSPECT_PORT_MAX).contains(&port) {
info!("Found IPv6 listen port {} for pid {}", port, pid);
return port;
}
}
}
Expand All @@ -91,31 +107,44 @@ pub fn get_process_listening_port(pid: i32) -> u16 {
}


pub fn get_inspect_port(pid: i32) -> u16 {
pub fn get_inspect_port(process_info: &ProcessInfo) -> u16 {
let process = match procfs::process::Process::new(process_info.pid) {
Ok(p) => p,
Err(_) => {return 0;}
};

let re = regex::Regex::new(r"inspect(?:-brk|-port)?=(?:(?:[0-9]{1,3}\.){3}[0-9]{1,3}:)?(\d+)")
.expect("Invalid regex pattern");

let cmdline = std::fs::read_to_string(format!("/proc/{}/cmdline", pid)).unwrap_or_default();


let cmdline = process_info.cmdline.clone().unwrap_or(String::new());

if let Some(captures) = re.captures(&cmdline) {
if let Some(port) = captures.get(1) {
info!("inspect port: {}", port.as_str());
return port.as_str().parse().unwrap_or(0);
}
}

let environ = std::fs::read_to_string(format!("/proc/{}/environ", pid)).unwrap_or_default();
let options = environ.split('\0').find(|element| element.starts_with("NODE_OPTIONS="));

if let Some(options) = options {
if let Some(captures) = re.captures(options) {
if let Some(port) = captures.get(1) {
info!("inspect port: {}", port.as_str());
return port.as_str().parse().unwrap_or(0);
let env = match process.environ() {
Ok(env) => env,
Err(_) => {return 0;}
};

match env.get(&std::ffi::OsString::from("NODE_OPTIONS")) {
Some(v) => match v.clone().into_string() {
Ok(s) => {
if let Some(captures) = re.captures(s.as_str()) {
if let Some(port) = captures.get(1) {
info!("inspect port: {}", port.as_str());
return port.as_str().parse().unwrap_or(0);
}
}
}
}
}

Err(_) => {}
},
None => {}
};

0
}

Expand Down

0 comments on commit c33aafa

Please sign in to comment.