diff --git a/.gitignore b/.gitignore index 96ef6c0..69db9d3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target Cargo.lock +*.exe diff --git a/Cargo.toml b/Cargo.toml index 87e4645..4725cea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,19 +6,21 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -actix-tls = "3.0.3" -actix-web = {version = "4.3.0", features = ["rustls","openssl"]} +#actix-tls = "3.0.3" +#actix-web = {version = "4.3.0", features = ["rustls","openssl"]} env_logger = "0.10.0" log = "0.4.17" mime = "0.3.16" openssl = "0.10.52" -rustls = "0.20.8" -rustls-pemfile = "1.0.2" +#rustls = "0.20.8" +#rustls-pemfile = "1.0.2" aes = "0.8.2" cfb-mode = "0.8.2" serde = {version="1.0.163",features = ['derive']} serde_json = {version = "1.0.96", features = ['std']} -#rsa = "0.9.2" +rsa = "0.9.2" rand = "0.8.5" md-5 = "0.10.5" hex-literal = "0.4.1" +actix-web = "4.4.0" +actix-files = "0.6.2" diff --git a/priv.pem b/priv.pem new file mode 100644 index 0000000..19409d9 --- /dev/null +++ b/priv.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAy63nybDg2d0l5Em5RTsx0QJ4WhuT4DwrzJD/SdPDbOotXE5B +iVycfNxcfXVSa74SvqThyQs4KasZyK/NWJN6Xyi7NQgh2xKYc3eVj8b8MSkhz5Y7 +631dscLQRR9sDiTf2+jR8umd6U9op/ZucaOUzaEcyHalryeeRwD8q7mtlBccL+5d +SVVWuPaJ/Oh4Oivk4qNunYHygQ/iw2vBgN3f6tB1yiKlUe0T51FS1yJcavWilp2J +A6XGEhh0OmFJX6wf5vPu9heTXGqnriClinXnXV1zUPDaa0udD8n2OV9NphozqD7T +T4pE68G65Xz/iLAaEudSg7f1Shu+VFtt/cF4NwIDAQABAoIBABHUjF0r2/s7218p +Pwv6+x5HdOllJE8LJXBtOb6o8vYxZ+gpPPPSmiu/ZLoM5RAOiHiNBEEDzOuvkVHF +Zhi8zF0mj9Y8JdlA6adODtc9KFhWDUzYDjB200FxAvzSG9+pxbkWysOqROB8Svai +jEJBe5DRa6zMNNk+WCJHdAHFKZde6IHO4LR+5/GmYKjHKxBcsJhzPs7ysEXquZXc +CjQK8k5qHbMA1bEBIOXFoq8rVZxr35+3Zpc5djWf4DPNE2uxvUnblo2apz/vwdOQ +uslmFsEVSlcp3JoSuERonsE1uOvH0kRDPgsO+kTQUWNKZ5TEJoNaPpu+89JRBsRR +AkeYjt0CgYEA8QnXtxFfd8vtL6pwo+j1HXgHBREJjjdbgrBs+uqEZ+jqdEVpjr4V +bRmt5u8bC9nOEb6+nSKN1to7WuIu+1yvdsAHt/FsXcIBVOnxrPr2LyU1dRg7NX5Q +83ZTat1xnDVGHiDNk5xP8XtiirSSTqwTMr+qkIVMXVaV+jkW91wByTMCgYEA2FJq +3xgYiW3QcHwMSL2JKq2DTR+tGhuQ9ArNNqhTQDbzAgqIjcaT0vfL7qQEdDFzLpr5 ++HT3Wzwz+DZ1MnQQrJdKyzZDfHcbs0DFaxkHAxf9XFwV0jRSXYtLGwwfz9mcX0yb +11MoPVxXJbzG1f50jbAt8+NqCy5oOv3/l/HE/O0CgYBxaWQqKu50e2saZmOhe9b5 +CqSi6aVJWRqhn0lntjiee6T1GEPWefGy58Y/Rnm/Vbfz+X/Oh5edZAlRdeMNOksE +4M3A6sNGSiY+QeUIsvxqqmNAuSoCvXBxXVdajN8L1LUtL9oKfh3PTXLMOLIueiB+ +XFhwr4eC01614W7A7HWaqQKBgQCbV/xFP1GHh2OzE3Hi3rFdA4OR49h0Mi2TAxrB +UHmQWKWD5rqPTXYkfyxksEY+hrBXXJV79csYKpCLg9f/ple/CVp9ufcWr5Yl0LK0 +qSFe+GBKbhqBfG9Vm80QnFFP+s6PpT0YkTAJeIFgqUMEs5lRkp49USd65hWVn4dn +vwgeNQKBgQDCp3Myat3Kndkc5ujfkNLmYFYzfhihGV/ihmXed+bT52fTah8W2F3K +bv1828pER8Kph/Qm1tAv/iZzh6hk/fqm5n/xXCABx0gNxw1zshjNZR1F1HD3xoTy +dRg9yAajXjVo2NGkgGMUdqUV9wW/uACJTxUjru42EsOfqawF2cZpuw== +-----END RSA PRIVATE KEY----- diff --git a/src/main.rs b/src/main.rs index 6bfbfe3..2181c65 100755 --- a/src/main.rs +++ b/src/main.rs @@ -2,17 +2,22 @@ #![allow(non_snake_case)] #![allow(dead_code)] #![allow(unused_imports)] -use actix_web::{get, http::header::ContentType, post, web, App, HttpRequest, HttpResponse, HttpServer}; +use actix_web::{Result, get, http::header::ContentType, post, web, App, HttpRequest, HttpResponse, HttpServer}; use aes::cipher::{AsyncStreamCipher, KeyIvInit}; use log::{debug, error, info, log_enabled, Level}; -use rustls::{Certificate, PrivateKey, ServerConfig}; use serde::{Deserialize, Serialize}; - -// Reading the cert -use rustls_pemfile::{certs, pkcs8_private_keys}; use std::fs::File; use std::io::BufReader; use std::io::Read; +use rsa::Pkcs1v15Encrypt; +use rsa::RsaPublicKey; +use rsa::pkcs8::DecodePublicKey; +use actix_files::NamedFile; +use std::path::PathBuf; + +// Reading the cert +//use rustls_pemfile::{certs, pkcs8_private_keys}; +//use rustls::{Certificate, PrivateKey, ServerConfig}; // AES encryption use openssl::rsa::{Padding, Rsa}; @@ -24,37 +29,22 @@ use md5::{Digest, Md5}; #[post("/basicinfo")] async fn basicinfo() -> HttpResponse { - println!("/basicinfo\nNot fully implemented!"); - /* - let pem = "-----BEGIN PUBLIC KEY----- - MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy63nybDg2d0l5Em5RTsx - 0QJ4WhuT4DwrzJD/SdPDbOotXE5BiVycfNxcfXVSa74SvqThyQs4KasZyK/NWJN6 - Xyi7NQgh2xKYc3eVj8b8MSkhz5Y7631dscLQRR9sDiTf2+jR8umd6U9op/ZucaOU - zaEcyHalryeeRwD8q7mtlBccL+5dSVVWuPaJ/Oh4Oivk4qNunYHygQ/iw2vBgN3f - 6tB1yiKlUe0T51FS1yJcavWilp2JA6XGEhh0OmFJX6wf5vPu9heTXGqnriClinXn - XV1zUPDaa0udD8n2OV9NphozqD7TT4pE68G65Xz/iLAaEudSg7f1Shu+VFtt/cF4 - NwIDAQAB - -----END PUBLIC KEY-----"; - */ + // This function is technically decrypting the plaintext into cipher text for the client to + // encrypt to read it. It's very backwards, but this is how the game works. I hate it. + println!("____________________________"); + println!("/basicinfo"); let mut key_file = File::open("priv.pem").unwrap(); - let mut key_buffer = Vec::new(); key_file.read_to_end(&mut key_buffer).unwrap(); - // Load the private key from the PEM data let rsa = Rsa::private_key_from_pem(&key_buffer).unwrap(); - - let plaintext = r#" - {'result':200,'response':{'base_url':'http://10.3.0.53/game/info','download_url':'http://10.3.0.53/download','key':'01234567890123456789012345678901','iv':'0123456789012345','tenpo_index':1337}} - "#; + let plaintext = r#"{'result':200,'response':{'base_url':'http://10.3.0.53/game/info','download_url':'http://10.3.0.53/download','key':'01234567890123456789012345678901','iv':'0123456789012345','tenpo_index':1337}}"#; let mut ciphertext = vec![0; rsa.size() as usize]; - rsa.public_encrypt(plaintext.as_bytes(), &mut ciphertext, Padding::PKCS1).unwrap(); + rsa.private_encrypt(plaintext.as_bytes(), &mut ciphertext, Padding::PKCS1).unwrap(); + println!("{:?}", &plaintext); println!("{:?}", String::from_utf8_lossy(&ciphertext)); - //let mut rng = rand::thread_rng(); - //let pub_key = RsaPublicKey::from_public_key_pem(pem).unwrap(); - //let ciphertext = pub_key.encrypt(&mut rng, Pkcs1v15Encrypt, &plaintext.as_bytes()).expect("failed to encrypt"); HttpResponse::Ok().append_header(ContentType::octet_stream()).body(ciphertext) } @@ -68,18 +58,21 @@ macro_rules! resp { #[get("/alive/{id}/Alive.txt")] async fn alive(id: web::Path, req: actix_web::HttpRequest) -> HttpResponse { + println!("____________________________"); println!("/alive/{}/Alive.txt", id); resp!("") } #[get("/alive/i.php")] async fn alive_i() -> HttpResponse { + println!("____________________________"); println!("/alive/i.php"); resp!("REMOTE ADDRESS:10.3.0.53\nSERVER NAME:LLSIFAC\nSERVER ADDR:10.3.0.53") } #[post("/service/card/incomALL.php")] async fn incomALL() -> HttpResponse { + println!("____________________________"); println!("/service/card/incomALL.php"); resp!("1+1") } @@ -93,23 +86,27 @@ async fn respone() -> HttpResponse { #[get("/server/FireAlert.php")] async fn fire_alert() -> HttpResponse { + println!("____________________________"); println!("/server/FireAlert.php"); resp!("OK") } #[get("/server/cursel.php")] async fn cursel() -> HttpResponse { + println!("____________________________"); println!("/server/cursel.php"); resp!("1\n") } #[get("/server/gameinfo.php")] async fn gameinfo() -> HttpResponse { + println!("____________________________"); println!("/server/gameinfo.php"); resp!("0\n3\n301000,test1\n302000,test2\n303000,test3\n") } #[post("/game/info")] async fn game_info() -> HttpResponse { + println!("____________________________"); // JSON type that is AES encrypted let plaintext = r#"{"result":200,"response":{"base_url":"http://10.3.0.53/game/next","information":[],"event_information":[],"encore_expiration_date":"2033-05-27"}}"#; @@ -121,7 +118,7 @@ async fn game_info() -> HttpResponse { let mut ciphertext = plaintext.as_bytes().to_vec(); Aes128CfbEnc::new(key.into(), iv.into()).encrypt(&mut ciphertext); - //println!("{:?}", String::from_utf8_lossy(&ciphertext)); + println!("{:?}", String::from_utf8_lossy(&ciphertext)); println!("/game/info"); HttpResponse::Ok().append_header(ContentType::octet_stream()).body(ciphertext) } @@ -136,8 +133,10 @@ pub struct Certify { } #[get("/server/certify.php")] -async fn certify(data: web::Query, req: HttpRequest) -> HttpResponse { +async fn certify() -> HttpResponse { + //async fn certify(data: web::Query, req: HttpRequest) -> HttpResponse { println!("/server/certify.php"); + /* dbg!(&data); let mut hasher = Md5::new(); let gid_bytes = "303801".as_bytes(); // LL game nesys id @@ -146,9 +145,9 @@ async fn certify(data: web::Query, req: HttpRequest) -> HttpResponse { let mut ticket = String::new(); for byte in hash_result { ticket.push_str(&format!("{:x?}", &byte)); - } + }*/ let res = format!( - "host=http://10.3.0.53 +"host=http://10.3.0.53 no=1337 name=LLServer pref=nesys @@ -176,6 +175,17 @@ async fn index(req: actix_web::HttpRequest) -> HttpResponse { HttpResponse::Ok().append_header(ContentType(mime::TEXT_PLAIN)).body("shit") } +async fn test(req: HttpRequest) -> Result { + println!("---"); + println!("Method: {:?}", req.method()); + println!("Host: {:?}", req.head().uri.host()); + println!("Path: {:?}", req.path()); + + let path: PathBuf = req.match_info().query("test.png").parse().unwrap(); + Ok(NamedFile::open(path)?) +} + +/* fn load_rustls_config() -> rustls::ServerConfig { // init server config builder with safe defaults let config = ServerConfig::builder().with_safe_defaults().with_no_client_auth(); @@ -196,11 +206,11 @@ fn load_rustls_config() -> rustls::ServerConfig { config.with_single_cert(cert_chain, keys.remove(0)).unwrap() } - +*/ #[actix_web::main] async fn main() -> std::io::Result<()> { env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); - let config = load_rustls_config(); + //let config = load_rustls_config(); info!("Certificates loaded."); println!("Started!"); HttpServer::new(|| { @@ -216,11 +226,12 @@ async fn main() -> std::io::Result<()> { .service(certify) .service(server_data) .service(basicinfo) + .route("/{test.png}",web::get().to(test)) .route("{path:.*}", web::get().to(index)) }) .bind("0.0.0.0:80")? .bind("0.0.0.0:5107")? - .bind_rustls("0.0.0.0:443", config)? +// .bind_rustls("0.0.0.0:443", config)? .run() .await } diff --git a/test.png b/test.png new file mode 100644 index 0000000..a959c2a Binary files /dev/null and b/test.png differ diff --git a/utils/pkcs8_public_key.pem b/utils/pkcs8_public_key.pem new file mode 100644 index 0000000..99c9ed2 --- /dev/null +++ b/utils/pkcs8_public_key.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy63nybDg2d0l5Em5RTsx +0QJ4WhuT4DwrzJD/SdPDbOotXE5BiVycfNxcfXVSa74SvqThyQs4KasZyK/NWJN6 +Xyi7NQgh2xKYc3eVj8b8MSkhz5Y7631dscLQRR9sDiTf2+jR8umd6U9op/ZucaOU +zaEcyHalryeeRwD8q7mtlBccL+5dSVVWuPaJ/Oh4Oivk4qNunYHygQ/iw2vBgN3f +6tB1yiKlUe0T51FS1yJcavWilp2JA6XGEhh0OmFJX6wf5vPu9heTXGqnriClinXn +XV1zUPDaa0udD8n2OV9NphozqD7TT4pE68G65Xz/iLAaEudSg7f1Shu+VFtt/cF4 +NwIDAQAB +-----END PUBLIC KEY----- diff --git a/utils/post.py b/utils/post.py new file mode 100644 index 0000000..4ebb859 --- /dev/null +++ b/utils/post.py @@ -0,0 +1,75 @@ +import requests +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives.asymmetric import rsa, padding +from cryptography.hazmat.primitives import hashes + +# URL to send the POST request to +url = 'http://10.3.0.141/basicinfo' + +# Send the POST request +response = requests.post(url, verify=False) + +if response.status_code == 200: + # Extract the encrypted data from the response + encrypted_data = response.content + + # Load the private key from the PEM file + private_key_file = 'private_key.pem' # Replace with your private key file + with open(private_key_file, 'rb') as key_file: + private_key = serialization.load_pem_private_key( + key_file.read(), + password=None, # If your key is password-protected, provide the password here + backend=default_backend() + ) + + # Decrypt the data with PKCS#1 v1.5 padding + decrypted_data = private_key.decrypt( + encrypted_data, + padding.PKCS1v15() + ) + + # Assuming the decrypted data is a UTF-8 encoded string, you can print it + print("Decrypted Data:", decrypted_data.decode('utf-8')) +else: + print("Failed to retrieve data. Status code:", response.status_code) + +""" +import requests +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives import padding +from cryptography.hazmat.primitives.asymmetric import rsa + +# URL to send the POST request to +url = 'http://10.3.0.141/basicinfo' + +# Send the POST request +response = requests.post(url, verify=False) + +if response.status_code == 200: + # Extract the encrypted data from the response + encrypted_data = response.content + + # Load the private key from the PEM file + private_key_file = 'private_key.pem' # Replace with your private key file + with open(private_key_file, 'rb') as key_file: + private_key = serialization.load_pem_private_key( + key_file.read(), + password=None, # If your key is password-protected, provide the password here + backend=default_backend() + ) + + # Decrypt the data with no padding + decrypted_data = private_key.decrypt( + encrypted_data, + padding.PKCS7(128) + #padding.PKCS1v15() # Use PKCS#1 v1.5 padding for no padding + ) + + # Assuming the decrypted data is a UTF-8 encoded string, you can print it + print("Decrypted Data:", decrypted_data.decode('utf-8')) +else: + print("Failed to retrieve data. Status code:", response.status_code) + +""" diff --git a/utils/private_key.pem b/utils/private_key.pem new file mode 100644 index 0000000..6b819ec --- /dev/null +++ b/utils/private_key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDLrefJsODZ3SXk +SblFOzHRAnhaG5PgPCvMkP9J08Ns6i1cTkGJXJx83Fx9dVJrvhK+pOHJCzgpqxnI +r81Yk3pfKLs1CCHbEphzd5WPxvwxKSHPljvrfV2xwtBFH2wOJN/b6NHy6Z3pT2in +9m5xo5TNoRzIdqWvJ55HAPyrua2UFxwv7l1JVVa49on86Hg6K+Tio26dgfKBD+LD +a8GA3d/q0HXKIqVR7RPnUVLXIlxq9aKWnYkDpcYSGHQ6YUlfrB/m8+72F5Ncaqeu +IKWKdeddXXNQ8NprS50PyfY5X02mGjOoPtNPikTrwbrlfP+IsBoS51KDt/VKG75U +W239wXg3AgMBAAECggEAEdSMXSvb+zvbXyk/C/r7Hkd06WUkTwslcG05vqjy9jFn +6Ck889KaK79kugzlEA6IeI0EQQPM66+RUcVmGLzMXSaP1jwl2UDpp04O1z0oWFYN +TNgOMHbTQXEC/NIb36nFuRbKw6pE4HxK9qKMQkF7kNFrrMw02T5YIkd0AcUpl17o +gc7gtH7n8aZgqMcrEFywmHM+zvKwReq5ldwKNAryTmodswDVsQEg5cWirytVnGvf +n7dmlzl2NZ/gM80Ta7G9SduWjZqnP+/B05C6yWYWwRVKVyncmhK4RGiewTW468fS +REM+Cw76RNBRY0pnlMQmg1o+m77z0lEGxFECR5iO3QKBgQDxCde3EV93y+0vqnCj +6PUdeAcFEQmON1uCsGz66oRn6Op0RWmOvhVtGa3m7xsL2c4Rvr6dIo3W2jta4i77 +XK92wAe38WxdwgFU6fGs+vYvJTV1GDs1flDzdlNq3XGcNUYeIM2TnE/xe2KKtJJO +rBMyv6qQhUxdVpX6ORb3XAHJMwKBgQDYUmrfGBiJbdBwfAxIvYkqrYNNH60aG5D0 +Cs02qFNANvMCCoiNxpPS98vupAR0MXMumvn4dPdbPDP4NnUydBCsl0rLNkN8dxuz +QMVrGQcDF/1cXBXSNFJdi0sbDB/P2ZxfTJvXUyg9XFclvMbV/nSNsC3z42oLLmg6 +/f+X8cT87QKBgHFpZCoq7nR7axpmY6F71vkKpKLppUlZGqGfSWe2OJ57pPUYQ9Z5 +8bLnxj9Geb9Vt/P5f86Hl51kCVF14w06SwTgzcDqw0ZKJj5B5Qiy/GqqY0C5KgK9 +cHFdV1qM3wvUtS0v2gp+Hc9Ncsw4si56IH5cWHCvh4LTXrXhbsDsdZqpAoGBAJtX +/EU/UYeHY7MTceLesV0Dg5Hj2HQyLZMDGsFQeZBYpYPmuo9NdiR/LGSwRj6GsFdc +lXv1yxgqkIuD1/+mV78JWn259xavliXQsrSpIV74YEpuGoF8b1WbzRCcUU/6zo+l +PRiRMAl4gWCpQwSzmVGSnj1RJ3rmFZWfh2e/CB41AoGBAMKnczJq3cqd2Rzm6N+Q +0uZgVjN+GKEZX+KGZd535tPnZ9NqHxbYXcpu/XzbykRHwqmH9CbW0C/+JnOHqGT9 ++qbmf/FcIAHHSA3HDXOyGM1lHUXUcPfGhPJ1GD3IBqNeNWjY0aSAYxR2pRX3Bb+4 +AIlPFSOu7jYSw5+prAXZxmm7 +-----END PRIVATE KEY----- diff --git a/utils/public_key.pem b/utils/public_key.pem new file mode 100644 index 0000000..99c9ed2 --- /dev/null +++ b/utils/public_key.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy63nybDg2d0l5Em5RTsx +0QJ4WhuT4DwrzJD/SdPDbOotXE5BiVycfNxcfXVSa74SvqThyQs4KasZyK/NWJN6 +Xyi7NQgh2xKYc3eVj8b8MSkhz5Y7631dscLQRR9sDiTf2+jR8umd6U9op/ZucaOU +zaEcyHalryeeRwD8q7mtlBccL+5dSVVWuPaJ/Oh4Oivk4qNunYHygQ/iw2vBgN3f +6tB1yiKlUe0T51FS1yJcavWilp2JA6XGEhh0OmFJX6wf5vPu9heTXGqnriClinXn +XV1zUPDaa0udD8n2OV9NphozqD7TT4pE68G65Xz/iLAaEudSg7f1Shu+VFtt/cF4 +NwIDAQAB +-----END PUBLIC KEY-----