Skip to content

⛵️ Available - Crystal Man-in-the-middle Toolkit

License

Notifications You must be signed in to change notification settings

636f7374/cherry.cr

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

79 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Cherry.cr - Man-in-the-middle Toolkit

Description

  • Because Crystal language is missing most OpenSSL bindings (libCrypto, libSSL).
  • Of course, Crystal official is always busy, it will not help you solve these problems.
    • In despair, I came across openssl.cr, which is a shabby OpenSSL binding.
    • This OpenSSL repository was last updated 5 years ago, Fortunately, most of its features are not completely broken.
    • So I started to test slowly and repair the broken things, And refer to Ruby prototype for redesign.
    • It took one month to fix most of the problems, and finally it was available after three months.
  • I think if I was using Rust then I would n’t have encountered these problems.
    • But this allows me to learn a lot, I hope it can help more people.
  • That's it, Thanks for using, If you encounter any problems, please let me know.
  • After a period of testing, thread safety is now supported.

Features

  • OpenSSL

    • Lib (libCrypto, libSSL)
      • There are many bindings in it, many related to loading / reading certificates.
      • libCrypto: (I.e. bio_*, evp_*, rsa_*, dsa_*, pem_*, asn1_*, x509_*).
      • libSSL: (I.e. ssl_ctx_use_certificate, ssl_ctx_use_privatekey).
    • Asn1 (Integer, Time)
      • Integer: Certificate serial number, very useful.
      • Time: Certificate validity period, very useful.
    • Bio (MemBIO)
      • MemBIO: OpenSSL memory buffer, Essential when making Certificate / (Private / Public) keys.
    • Nid
      • Certificate subject id flag, Essential when making Certificate.
      • NID: (I.e. subject_alt_name, ext_usage, usage).
    • Pkey (PKey, DSA, RSA)
      • Essential when (create / read) Public / Private Key.
      • I encountered a memory leak problem here, it has been fixed.
    • SSL (Context)
      • Context: Support loading certificate / private key files from memory.
    • X509 (ExtensionFactory, Request, SuperCertificate, SuperName).
      • ExtensionFactory: Certificate Subject Add / Remove, very important.
      • Request: I don't seem to use it, but I also made.
      • SuperCertificate: Generate certificate requires it.
      • SuperName: issuer_name, subject_name, Generate certificate requires it.
  • MITM

    • Mitm Slightly complicated but worth it, low memory usage.
    • Client: Wrapper for OpenSSL::SSL::Socket::Client.
    • Server: Wrapper for OpenSSL::SSL::Socket::Server.
    • Context: Convenient and fast certificate generation, for Man-in-the-middle.

Tips

  • This repository contains OpenSSL and Network components.
    • Crystal HTTP::Client components are highly integrated with OpenSSL.

Next

  • More specification tests.
  • Troubleshooting Deep Memory Errors / Memory Leaks (More stress tests?)
  • ...

Usage

  • Simple Mitm Server (Need to be used with Carton.cr)
require "base64"
require "carton"
require "cherry"

# This is a simple design, please do not use it directly.

def handle_client(context, client : Carton::Socket)
  return client.close unless request = client.request_payload

  STDOUT.puts [client]

  case {client.tunnel_mode, client.traffic_type}
  when {true, Carton::Traffic::HTTPS}
    client = MITM::Server.upgrade client, request, context

    buffer = uninitialized UInt8[4096_i32]
    length = client.read buffer.to_slice
    puts String.new buffer.to_slice[0_i32, length]
  end

  client.close
end

# Durian
servers = [] of Tuple(Socket::IPAddress, Durian::Protocol)
servers << Tuple.new Socket::IPAddress.new("8.8.8.8", 53_i32), Durian::Protocol::UDP
servers << Tuple.new Socket::IPAddress.new("1.1.1.1", 53_i32), Durian::Protocol::UDP
resolver = Durian::Resolver.new servers
resolver.ip_cache = Durian::Resolver::Cache::IPAddress.new

# Carton
tcp_server = TCPServer.new "0.0.0.0", 1234_i32
carton = Carton::Server.new tcp_server, resolver

carton.authentication = Carton::Authentication::None
carton.client_timeout = Carton::TimeOut.new
carton.remote_timeout = Carton::TimeOut.new

certificate = Base64.decode_string "Something..."
private_key = Base64.decode_string "Something..."
context = MITM::Context.new certificate, private_key

# Authentication (Optional)
# carton.authentication = Carton::Authentication::Basic
# carton.on_auth = ->(user_name : String, password : String) do
#  STDOUT.puts [user_name, password]
#  Carton::Verify::Pass
# end

loop do
  socket = carton.accept?

  spawn do
    next unless client = socket
    next unless client = carton.process client

    handle_client context, client
  end
end
  • Simple HTTP Client

    • ...

Used as Shard

Add this to your application's shard.yml:

dependencies:
  cherry:
    github: 636f7374/cherry.cr

Installation

$ git clone https://github.com/636f7374/cherry.cr.git

Development

$ make test

References

Related

Credit

Contributors

Name Creator Maintainer Contributor
636f7374
datanoise

License

  • MIT License