From 42da6121131a222ea8ceda1810884733fa9a4224 Mon Sep 17 00:00:00 2001
From: evilsocket
Date: Mon, 18 Aug 2025 19:14:05 +0200
Subject: [PATCH 1/4] hotfix: hotfix 2 for tcp.proxy
---
modules/tcp_proxy/tcp_proxy_script.go | 78 +++++++---------------
modules/tcp_proxy/tcp_proxy_script_test.go | 51 ++++++++++++++
2 files changed, 75 insertions(+), 54 deletions(-)
diff --git a/modules/tcp_proxy/tcp_proxy_script.go b/modules/tcp_proxy/tcp_proxy_script.go
index 60f103ea..50956ea0 100644
--- a/modules/tcp_proxy/tcp_proxy_script.go
+++ b/modules/tcp_proxy/tcp_proxy_script.go
@@ -1,6 +1,7 @@
package tcp_proxy
import (
+ "encoding/json"
"net"
"strings"
@@ -62,60 +63,29 @@ func (s *TcpProxyScript) OnData(from, to net.Addr, data []byte, callback func(ca
}
func toByteArray(ret interface{}) []byte {
- // Handle different array types that otto.Export() might return
- switch v := ret.(type) {
- case []interface{}:
- // Mixed type array
- result := make([]byte, len(v))
- for i, elem := range v {
- if num, ok := toNumber(elem); ok && num >= 0 && num <= 255 {
- result[i] = byte(num)
- } else {
- log.Error("array element at index %d is not a valid byte value %+v", i, elem)
- return nil
- }
- }
- return result
- case []int64:
- // Array of integers
- result := make([]byte, len(v))
- for i, num := range v {
- if num >= 0 && num <= 255 {
- result[i] = byte(num)
- } else {
- log.Error("array element at index %d is not a valid byte value %d", i, num)
- return nil
- }
- }
- return result
- case []float64:
- // Array of floats
- result := make([]byte, len(v))
- for i, num := range v {
- if num >= 0 && num <= 255 {
- result[i] = byte(num)
- } else {
- log.Error("array element at index %d is not a valid byte value %f", i, num)
- return nil
- }
- }
- return result
- default:
- log.Error("unexpected array type returned from onData: %T, value = %+v", ret, ret)
- return nil
- }
-}
+ // this approach is a bit hacky but it handles all cases
-// toNumber tries to convert an interface{} to a float64
-func toNumber(v interface{}) (float64, bool) {
- switch n := v.(type) {
- case float64:
- return n, true
- case int64:
- return float64(n), true
- case int:
- return float64(n), true
- default:
- return 0, false
+ // serialize ret to JSON
+ if jsonData, err := json.Marshal(ret); err == nil {
+ // attempt to deserialize as []float64
+ var back2Array []float64
+ if err := json.Unmarshal(jsonData, &back2Array); err == nil {
+ result := make([]byte, len(back2Array))
+ for i, num := range back2Array {
+ if num >= 0 && num <= 255 {
+ result[i] = byte(num)
+ } else {
+ log.Error("array element at index %d is not a valid byte value %d", i, num)
+ return nil
+ }
+ }
+ return result
+ } else {
+ log.Error("failed to deserialize %+v to []float64: %v", ret, err)
+ }
+ } else {
+ log.Error("failed to serialize %+v to JSON: %v", ret, err)
}
+
+ return nil
}
diff --git a/modules/tcp_proxy/tcp_proxy_script_test.go b/modules/tcp_proxy/tcp_proxy_script_test.go
index cb09b052..27bdc099 100644
--- a/modules/tcp_proxy/tcp_proxy_script_test.go
+++ b/modules/tcp_proxy/tcp_proxy_script_test.go
@@ -116,3 +116,54 @@ func TestOnData_ReturnsDynamicArray(t *testing.T) {
}
}
}
+
+func TestOnData_ReturnsMixedArray(t *testing.T) {
+ jsCode := `
+ function charToInt(value) {
+ return value.charCodeAt()
+ }
+
+ function onData(from, to, data) {
+ st_data = String.fromCharCode.apply(null, data)
+ if( st_data.indexOf("mysearch") != -1 ) {
+ payload = "mypayload";
+ st_data = st_data.replace("mysearch", payload);
+ res_int_arr = st_data.split("").map(charToInt) // []uint16
+ res_int_arr[0] = payload.length + 1; // first index is float64 and rest []uint16
+ return res_int_arr;
+ }
+ return data;
+ }
+ `
+
+ plug, err := plugin.Parse(jsCode)
+ if err != nil {
+ t.Fatalf("Failed to parse plugin: %v", err)
+ }
+
+ script := &TcpProxyScript{
+ Plugin: plug,
+ doOnData: plug.HasFunc("onData"),
+ }
+
+ from := &net.TCPAddr{IP: net.ParseIP("192.168.1.1"), Port: 1234}
+ to := &net.TCPAddr{IP: net.ParseIP("192.168.1.6"), Port: 5678}
+ data := []byte("Hello mysearch world")
+
+ result := script.OnData(from, to, data, nil)
+ expected := []byte("\x0aello mypayload world")
+
+ if result == nil {
+ t.Fatal("Expected non-nil result when callback returns array of integers")
+ }
+
+ if len(result) != len(expected) {
+ t.Fatalf("Expected result length %d, got %d", len(expected), len(result))
+ }
+
+ for i, b := range result {
+ if b != expected[i] {
+ t.Errorf("Expected byte at index %d to be %d, got %d", i, expected[i], b)
+ }
+ }
+}
From 4ec2753fad4a26096ea5c4cc11a38baaf39a3830 Mon Sep 17 00:00:00 2001
From: evilsocket
Date: Mon, 18 Aug 2025 19:15:44 +0200
Subject: [PATCH 2/4] releasing version 2.41.4
---
core/banner.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/core/banner.go b/core/banner.go
index 5fdcebae..1a63f0c8 100644
--- a/core/banner.go
+++ b/core/banner.go
@@ -2,7 +2,7 @@ package core
const (
Name = "bettercap"
- Version = "2.41.3"
+ Version = "2.41.4"
Author = "Simone 'evilsocket' Margaritelli"
Website = "https://bettercap.org/"
)
From 204997c8b51af7bc3c2c68ecfb232bbfcb840207 Mon Sep 17 00:00:00 2001
From: evilsocket
Date: Sat, 23 Aug 2025 14:22:11 +0200
Subject: [PATCH 3/4] misc: small fix or general refactoring i did not bother
commenting
---
README.md | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/README.md b/README.md
index 299e1d78..c1ecdf39 100644
--- a/README.md
+++ b/README.md
@@ -16,6 +16,10 @@
+
+
+
+
From 1001cea8f2af70fdcafae1dc08be3e52a17a7bbf Mon Sep 17 00:00:00 2001
From: evilsocket
Date: Sat, 23 Aug 2025 17:12:07 +0200
Subject: [PATCH 4/4] misc: small fix or general refactoring i did not bother
commenting
---
README.md | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/README.md b/README.md
index c1ecdf39..ed1a583b 100644
--- a/README.md
+++ b/README.md
@@ -16,9 +16,7 @@
-
-
-
+