@@ -17,6 +17,9 @@ func printHelpMessage() {
1717 fmt .Println ()
1818 fmt .Println ("Specify the bytes of the payload to send by entering a list of integers separated by spaces." )
1919 fmt .Println ("Integers can be in base 10, binary (start with 0b), or hex (start with 0x)." )
20+ fmt .Println ("To toggle between ASCII and byte modes, type 'mode'." )
21+ fmt .Println ("In ASCII mode, text will be sent directly as bytes." )
22+ fmt .Println ("In ASCII mode, you can use escape sequences like \\ x00 to include specific byte values." )
2023 fmt .Println ("To resend the most recent payload, press the up arrow followed by Enter." )
2124 fmt .Println ("To view the history of previously sent payloads, type 'h'." )
2225 fmt .Println ("h <#> - resends the payload with the given history item number." )
@@ -69,26 +72,74 @@ func promptConnInfo(scanner *bufio.Scanner) (string, int, error) {
6972 return host , int (parsedPort ), nil
7073}
7174
75+ // Parses ASCII escape sequences in the input string and returns the corresponding byte array
76+ func parseAsciiEscapeSequences (input string ) ([]byte , error ) {
77+ // In ASCII mode, process escape sequences
78+ result := []byte {}
79+ for i := 0 ; i < len (input ); i ++ {
80+ if input [i ] == '\\' && i + 1 < len (input ) {
81+ if i + 3 < len (input ) && input [i + 1 ] == 'x' {
82+ // Handle \xHH escape sequence
83+ if hexByte , err := strconv .ParseUint (input [i + 2 :i + 4 ], 16 , 8 ); err == nil {
84+ result = append (result , byte (hexByte ))
85+ i += 3 // Skip the next 3 characters (\xHH)
86+ continue
87+ }
88+ }
89+ // Handle other escape sequences
90+ switch input [i + 1 ] {
91+ case 'n' :
92+ result = append (result , '\n' )
93+ case 'r' :
94+ result = append (result , '\r' )
95+ case 't' :
96+ result = append (result , '\t' )
97+ case '\\' :
98+ result = append (result , '\\' )
99+ case '0' :
100+ result = append (result , 0 )
101+ default :
102+ // If not a recognized escape, just add the character
103+ result = append (result , input [i + 1 ])
104+ }
105+ i ++ // Skip the next character (the one after \)
106+ } else {
107+ // Regular character
108+ result = append (result , input [i ])
109+ }
110+ }
111+ return result , nil
112+ }
113+
72114// Prompts for user input, either a payload or other command.
73115// Returns the payload (if one was given) formatted as a byte array.
74- func promptInput (scanner * bufio.Scanner , history [][]byte ) ([]byte , error ) {
116+ func promptInput (scanner * bufio.Scanner , history [][]byte , isAsciiMode bool ) ([]byte , error ) {
75117 fmt .Print ("Payload: " )
76118 scanner .Scan ()
77119 if err := scanner .Err (); err != nil {
78120 return nil , fmt .Errorf ("error scanning input: %v" , err )
79121 }
80- inputTokens := strings .Fields (scanner .Text ())
81- if len (inputTokens ) == 0 {
122+
123+ input := scanner .Text ()
124+ inputTokens := strings .Fields (input )
125+ if len (input ) == 0 {
82126 return nil , fmt .Errorf ("no input" )
83127 }
84128
85129 // Print help message
86- if inputTokens [ 0 ] == "help" {
130+ if input == "help" {
87131 printHelpMessage ()
88132 return nil , nil
89133 }
134+
135+ // Toggle mode command
136+ if input == "mode" {
137+ return []byte ("__MODE_TOGGLE__" ), nil
138+ }
139+
90140 // Check for history commands
91- if inputTokens [0 ] == "h" {
141+ if strings .HasPrefix (input , "h" ) && (len (input ) == 1 || input [1 ] == ' ' ) {
142+ inputTokens = strings .Fields (input )
92143 if len (inputTokens ) == 1 {
93144 // print history
94145 if len (history ) == 0 {
@@ -121,7 +172,7 @@ func promptInput(scanner *bufio.Scanner, history [][]byte) ([]byte, error) {
121172 // print usage info
122173 return nil , fmt .Errorf ("usage: h [item number]" )
123174 }
124- } else if inputTokens [ 0 ] == "\x1b [A" && len ( inputTokens ) == 1 { // read up arrow
175+ } else if input == "\x1b [A" { // read up arrow
125176 // resend most recent payload
126177 if len (history ) == 0 {
127178 fmt .Println ("History is empty." )
@@ -130,38 +181,65 @@ func promptInput(scanner *bufio.Scanner, history [][]byte) ([]byte, error) {
130181 return history [len (history )- 1 ], nil
131182 }
132183
133- // Loop adding byte from input line to payload
134- payload := make ([]byte , 0 , 10 )
135- for _ , str := range inputTokens {
136- parsedInt64 , err := strconv .ParseUint (str , 0 , 64 )
137- if err != nil {
138- return nil , fmt .Errorf ("error parsing payload: %v" , err )
184+ // Process payload based on current mode
185+ if isAsciiMode {
186+ return parseAsciiEscapeSequences (input )
187+ } else {
188+ // Byte mode - original behavior
189+ // Loop adding byte from input line to payload
190+ payload := make ([]byte , 0 , 10 )
191+ for _ , str := range inputTokens {
192+ parsedInt64 , err := strconv .ParseUint (str , 0 , 64 )
193+ if err != nil {
194+ return nil , fmt .Errorf ("error parsing payload: %v" , err )
195+ }
196+ byteBuffer := make ([]byte , 8 )
197+ binary .BigEndian .PutUint64 (byteBuffer , parsedInt64 )
198+ payload = append (payload , bytes .TrimLeft (byteBuffer , "\x00 " )... )
139199 }
140- byteBuffer := make ([]byte , 8 )
141- binary .BigEndian .PutUint64 (byteBuffer , parsedInt64 )
142- payload = append (payload , bytes .TrimLeft (byteBuffer , "\x00 " )... )
200+ return payload , nil
143201 }
144- return payload , nil
145202}
146203
147204// Loop prompting for input.
148205func mainInputLoop (scanner * bufio.Scanner , conn * net.UDPConn ) {
149206 history := make ([][]byte , 0 , 20 )
207+ isAsciiMode := false
150208 for {
151- payload , err := promptInput (scanner , history )
209+ // Show mode in prompt
210+ if isAsciiMode {
211+ fmt .Print ("Mode: ASCII\n " )
212+ } else {
213+ fmt .Print ("Mode: Bytes\n " )
214+ }
215+
216+ payload , err := promptInput (scanner , history , isAsciiMode )
152217 if err != nil {
153218 fmt .Println ("Error reading input:" , err )
154219 continue
155220 }
156221 if payload == nil { // no payload given
157222 continue
158223 }
224+
225+ // Handle mode toggle command
226+ if bytes .Equal (payload , []byte ("__MODE_TOGGLE__" )) {
227+ isAsciiMode = ! isAsciiMode
228+ fmt .Printf ("Switched to %s mode\n " , map [bool ]string {true : "ASCII" , false : "Bytes" }[isAsciiMode ])
229+ continue
230+ }
231+
159232 // Add payload to history (if not repeat of most recent payload)
160233 if len (history ) == 0 || ! slices .Equal (payload , history [len (history )- 1 ]) {
161234 history = append (history , payload )
162235 }
163236 // Send payload over connection
164- fmt .Printf ("\t Sending payload %# x\n " , payload )
237+ if isAsciiMode {
238+ fmt .Printf ("\t Sending ASCII: '%s'\n " , payload )
239+ fmt .Printf ("\t As bytes: %# x\n " , payload )
240+ } else {
241+ fmt .Printf ("\t Sending payload %# x\n " , payload )
242+ }
165243 if err := sendOverUDP (conn , payload ); err != nil {
166244 fmt .Println ("\t Error sending payload:" , err )
167245 }
0 commit comments