{"id":90,"date":"2013-04-02T12:39:30","date_gmt":"2013-04-02T20:39:30","guid":{"rendered":"http:\/\/www.android-decompiler.com\/blog\/?p=90"},"modified":"2021-09-10T13:52:00","modified_gmt":"2021-09-10T21:52:00","slug":"a-look-inside-an-android-app-protector","status":"publish","type":"post","link":"https:\/\/www.pnfsoftware.com\/blog\/a-look-inside-an-android-app-protector\/","title":{"rendered":"A look inside an Android app protector"},"content":{"rendered":"<p>Let&#8217;s have a quick look at one feature of this well-known Android application protector, the string encryption mechanism. The app in question is a version of Cyanide.<\/p>\n<p>First, <strong>access to strings inside a protected class are replaced by calls to a static private decryption routine<\/strong>. That routine accesses <strong>a static private array containing all protected strings<\/strong> within the class. That array is created by the class initializer upon loading:<\/p>\n<p><a href=\"http:\/\/www.android-decompiler.com\/blog\/wp-content\/uploads\/2013\/04\/1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-95\" src=\"http:\/\/www.android-decompiler.com\/blog\/wp-content\/uploads\/2013\/04\/1.png\" alt=\"1\" width=\"850\" height=\"421\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2013\/04\/1.png 850w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2013\/04\/1-300x148.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2013\/04\/1-624x309.png 624w\" sizes=\"auto, (max-width: 850px) 100vw, 850px\" \/><\/a><\/p>\n<p>The decryption routine usually takes 3 arguments, although in some simpler cases, it may only take two arguments. The arguments may also be shuffled. (Note: from a Dalvik standpoint, that routine is oddly structured. Although JEB&#8217;s decompiled output is structurally fine, a for-loop construct cannot be created, mainly because of the irregular jump inside the first if-cond branch.)<\/p>\n<p>The screenshot below represents that decryption routine. The name was obfuscated by the app protector. Notice the constant numerals that have been circled in that code snippet: they are the decryption routine characteristics.<\/p>\n<p><a href=\"http:\/\/www.android-decompiler.com\/blog\/wp-content\/uploads\/2013\/04\/2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-96\" src=\"http:\/\/www.android-decompiler.com\/blog\/wp-content\/uploads\/2013\/04\/2.png\" alt=\"2\" width=\"515\" height=\"597\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2013\/04\/2.png 515w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2013\/04\/2-258x300.png 258w\" sizes=\"auto, (max-width: 515px) 100vw, 515px\" \/><\/a><\/p>\n<p>The following screenshot shows the same piece of code after marking it up. As you can see, the encryption algorithm is fairly simple: the current output character is derived from the previous character as well as the current byte of the <em>encryptedStrings<\/em> array. A constant (-8 in this case) is added to yield the final character. The initial length (<em>length<\/em>) as well as initial character (<em>curChar<\/em>) are also offset by hard-coded constants. These three constants (0x3E, 0x199, -8) characterize the decryption routine, and are unique for each routine. The <em>curChar<\/em> parameter acts as the decryption key.<\/p>\n<p><a href=\"http:\/\/www.android-decompiler.com\/blog\/wp-content\/uploads\/2013\/04\/3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-97\" src=\"http:\/\/www.android-decompiler.com\/blog\/wp-content\/uploads\/2013\/04\/3.png\" alt=\"3\" width=\"592\" height=\"592\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2013\/04\/3.png 592w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2013\/04\/3-150x150.png 150w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2013\/04\/3-300x300.png 300w\" sizes=\"auto, (max-width: 592px) 100vw, 592px\" \/><\/a><\/p>\n<p>You may customize this Python script to decrypt the strings:<\/p>\n<pre>#!\/usr\/bin\/python\n# decryptor\n\n# customize\nstrings = [0x4C, 0xE, 2, 9, -7, 0x10, -54, 0x3E, 0x17, -9, -44, 0x4C, 0xA, ...]\nc0, c1, c2 = (0x199, 0x3E, -8)\n\ndef decrypt(length, curChar, pos):\n  length += c0\n  curChar += c1\n  r = ''\n  for i in range(length):\n    r += chr(curChar &amp; 0xFF)\n    curEncodedChar = strings[pos]\n    pos += 1\n    curChar = curChar + curEncodedChar + c2\n  return r<\/pre>\n<p>Combined with reflection (another feature of the protector), the protection can be pretty effective.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Let&#8217;s have a quick look at one feature of this well-known Android application protector, the string encryption mechanism. The app in question is a version of Cyanide. First, access to strings inside a protected class are replaced by calls to a static private decryption routine. That routine accesses a static private array containing all protected &hellip; <a href=\"https:\/\/www.pnfsoftware.com\/blog\/a-look-inside-an-android-app-protector\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">A look inside an Android app protector<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[15,3,5],"tags":[],"class_list":["post-90","post","type-post","status-publish","format-standard","hentry","category-android","category-decompilation","category-obfuscation"],"_links":{"self":[{"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/posts\/90","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/comments?post=90"}],"version-history":[{"count":0,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/posts\/90\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/media?parent=90"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/categories?post=90"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/tags?post=90"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}