view this document with Notepad 800*600 L ZZZZZZ RRRRR SSSSS L Z R R S L aaa Z aaa R R u u S L a Z a RRRRR u u SSSSS XX L aaaa Z aaaa R R u u S XXXX L a a Z a a R R u u S XXXXXX LLLLLLL aaaaa ZZZZZZZ aaaaa R R uuuuu SSSSSS XXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX XXXXXX XXXX proudly presents his 4.Cracking Tutorial (29.03.1999) XX This time I show you how to locate strings in C++ Builder programs that are not hardcoded. It is pretty easy. I found it when I coded the Hellforge General CrackMe II. So don't read on if you haven't cracked it, yet. This will steal your fun (and mine when I'm thinking how much reversers will sit in front of their PC and don't have an idea how to start.) A little example: * Referenced by a CALL at Address: |:00403ACA | :0040161C 55 push ebp :0040161D 8BEC mov ebp, esp :0040161F 81C43CFFFFFF add esp, FFFFFF3C :00401625 B87C544000 mov eax, 0040547C :0040162A E82D270000 call 00403D5C :0040162F 66C7854CFFFFFF0800 mov word ptr [ebp+FFFFFF4C], 0008 :00401638 8D45F4 lea eax, dword ptr [ebp-0C] * Reference To: Project1.System::AnsiString::AnsiString(void()) | :0040163B E808070000 call 00401D48 :00401640 50 push eax :00401641 FF8558FFFFFF inc dword ptr [ebp+FFFFFF58] * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040160B(C) | :00401647 8D45F8 lea eax, dword ptr [ebp-08] :0040164A B252 mov dl, 52 :0040164C E8DB280000 call 00403F2C :00401651 50 push eax :00401652 FF8558FFFFFF inc dword ptr [ebp+FFFFFF58] :00401658 8D45FC lea eax, dword ptr [ebp-04] :0040165B B257 mov dl, 57 :0040165D E8CA280000 call 00403F2C :00401662 FF8558FFFFFF inc dword ptr [ebp+FFFFFF58] :00401668 5A pop edx :00401669 59 pop ecx :0040166A E8BD290000 call 0040402C :0040166F 8D45F4 lea eax, dword ptr [ebp-0C] :00401672 50 push eax * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00401608(C) | :00401673 8D45EC lea eax, dword ptr [ebp-14] * Reference To: Project1.System::AnsiString::AnsiString(void()) | :00401676 E8CD060000 call 00401D48 :0040167B 50 push eax :0040167C FF8558FFFFFF inc dword ptr [ebp+FFFFFF58] :00401682 8D45F0 lea eax, dword ptr [ebp-10] :00401685 B24F mov dl, 4F :00401687 E8A0280000 call 00403F2C :0040168C 8BD0 mov edx, eax :0040168E FF8558FFFFFF inc dword ptr [ebp+FFFFFF58] :00401694 59 pop ecx :00401695 58 pop eax :00401696 E891290000 call 0040402C :0040169B 8D45EC lea eax, dword ptr [ebp-14] :0040169E 50 push eax :0040169F 8D45E4 lea eax, dword ptr [ebp-1C] * Reference To: Project1.System::AnsiString::AnsiString(void()) | :004016A2 E8A1060000 call 00401D48 :004016A7 50 push eax :004016A8 FF8558FFFFFF inc dword ptr [ebp+FFFFFF58] :004016AE 8D45E8 lea eax, dword ptr [ebp-18] :004016B1 B24E mov dl, 4E :004016B3 E874280000 call 00403F2C :004016B8 8BD0 mov edx, eax :004016BA FF8558FFFFFF inc dword ptr [ebp+FFFFFF58] :004016C0 59 pop ecx :004016C1 58 pop eax :004016C2 E865290000 call 0040402C :004016C7 8D45E4 lea eax, dword ptr [ebp-1C] :004016CA 50 push eax :004016CB 8D45DC lea eax, dword ptr [ebp-24] * Reference To: Project1.System::AnsiString::AnsiString(void()) | :004016CE E875060000 call 00401D48 :004016D3 50 push eax :004016D4 FF8558FFFFFF inc dword ptr [ebp+FFFFFF58] :004016DA 8D45E0 lea eax, dword ptr [ebp-20] :004016DD B247 mov dl, 47 :004016DF E848280000 call 00403F2C :004016E4 8BD0 mov edx, eax :004016E6 FF8558FFFFFF inc dword ptr [ebp+FFFFFF58] :004016EC 59 pop ecx :004016ED 58 pop eax :004016EE E839290000 call 0040402C :004016F3 8D45DC lea eax, dword ptr [ebp-24] :004016F6 50 push eax :004016F7 8D45D4 lea eax, dword ptr [ebp-2C] ... Think you didn't get much from this code snippet, so I'll explain: I coded the word WRONG in C++ in this way String wrong=String(char(87))+String(char(82))+String(char(79))+String(char(78))+String(char(71)) When you look some lines below * Reference To: Project1.System::AnsiString::AnsiString(void()) you see something like mov dl, XX (00<=XX<=FF). Let's take these lines: :0040164A B252 mov dl, 52 :0040165B B257 mov dl, 57 :00401685 B24F mov dl, 4F :004016B1 B24E mov dl, 4E :004016DD B247 mov dl, 47 Guess what. These are the hex-values for decimal and ASCII: 52 = 87 = W 57 = 82 = R 4F = 79 = O 4E = 78 = N 47 = 71 = G Where are they saved so that we can locate them during the program ? The address where the char is to be saved is calculated in the first CALL after the mov dl, XX. Look at the EBP register. If a new value is copied near it this is a pointer to the address where the char is stored. (It seems to be EBP-08, but I am no ASM god so look at changes near EBP) Now the address is increased and the new value is assigned to EBP and the next char is copied to the next address. This is strange: C++ Builder copies the Bytes to the RAM like this: First char (W) is stored. Then second char (R) is stored above and below they are added. Then the third char (O) is stored below the WR and WR is added with O 16 bytes later and so on. [00972170] - 00000052 R... [00972174] - 00000012 .... ;; ??? (can anybody tell me what this line means?) [00972178] - 00000001 .... ;; ??? (can anybody tell me what this line means?) [0097217C] - 00000001 .... [00972180] - 00000057 W... [00972184] - 00000012 .... [00972188] - 00000001 .... [0097218C] - 00000002 .... [00972190] - 00005257 WR.. [00972194] - 00000012 .... [00972198] - 00000001 .... [0097219C] - 00000001 .... [009721A0] - 0000004f O... [009721A4] - 00000012 .... [009721A8] - 00000001 .... [009721AC] - 00000003 .... [009721B0] - 004f5257 WRO. [009721B4] - 00000012 .... [009721B8] - 00000001 .... [009721BC] - 00000001 .... [009721C0] - 0000004e N... [009721C4] - 00000016 .... [009721C8] - 00000001 .... [009721CC] - 00000004 .... [009721D0] - 4e4f5257 WRON [009721D8] - 00000012 .... [009721DC] - 00000001 .... [009721E0] - 00000001 .... [009721E4] - 00000047 G... [009721E8] - 00000016 .... [009721EC] - 00000001 .... [009721F0] - 00000005 .... [009721F4] - 4e4f5257 WRON [009721F8] - 00000047 G... [009721D8] - 00000012 .... [009721DC] - 00000001 .... [009721E0] - 00000001 .... Isn't it possible, that they store it like this immediately: Put first char to 00972170, increase pointer by 1 byte and copy the next char to 00972171 and so on. [00972170] - 4e4f5257 WRON [009721F4] - 00000047 G... In this way you only need 5 bytes of RAM to store WRONG. In Borland's way they need 40 bytes. Little Explaination: You surely recognized that the hex-values don't fit to the ASCII values. You have to turn the hex-values: 4e4f5257 will be 57524f4e. This is, because the RAM is counted downwards or something like that. For an exact answer ask in a forum at http://www.proweb.co.uk/~greenway. BTW Hope my tutorial was helpful for you and see you again in my next tutorial. If not see visit our webpage. Greets to: tKC, Ed!son, Moral Insanity, The Sandman, Eternal Bliss, DaVinci and all [hf] members VI. All Tutorials by LaZaRuS [hf] #| date | name |version|W32Dasm|Soft-Ice|kind of crack | -|--------|------------------|-------|-------|--------|-------------------------| 1|20.01.99|Jaylock |1,0,0,1| (X) | (X) |serial# | 2|31.01.99|Goldwave |4.02 | (X) | (X) |serial#,nag-screens | 3|28.03.99|AxMan |3.00 | (X) | (X) |serial#,remove date-limit| 4|29.03.99|C++Builder Strings| | (X) | (X) |how to find strings in | | | | | | |C++ Builder that are not | | | | | | |hardcoded LaZaRuS [hf] Visit Hellforge at http://members.xoom.com/hell_crack for more tutorials and high quality cracking links. If you want to mail me: lazarus666@gnwmail.com