Results 1 to 6 of 6
  1. #1
    why06's Avatar
    Join Date
    Jul 2009
    Gender
    male
    Location
    IBM
    Posts
    4,304
    Reputation
    170
    Thanks
    2,203
    My Mood
    Flirty

    Lena's Tuts: 02. Keyfiling the reverseme + assembler

    "I've decided to stop calling this series 'Corrections' because there are very few problems, and I don't want to be disrespectful since these tuts are excellent and for the most part correct." -why06

    Lena's Tuts Summaries
    02. Keyfiling the reverseme + assembler


    Intro:
    Ok. Lets get started. This one is all about Keyfiling. It uses the ReverseMe.exe from tutorial one so if you finished that one this should be a breeze. However it introduces some new concepts you should look out for. I will be covering those as well as presenting some supplemental tutorials and information for those interested.

    What this Covers?
    • Hexadecimal and Binary Number Systems
    • Windows API's: ReadFile & CreateFile
    • Loop Disassembly
    • If-Else Logic


    Summary:
    This Tutorial is actually very easy, up until you get to this point:
    Code:
    004010AE    .  85C0                     TEST EAX,EAX                                  ;  kernel32.BaseThreadInitThunk
    004010B0       75 02                    JNZ SHORT reverseM.004010B4
    004010B2    .  EB 43                    JMP SHORT reverseM.004010F7
    004010B4    >  33DB                     XOR EBX,EBX
    004010B6    .  33F6                     XOR ESI,ESI
    004010B8    .  833D 73214000 10         CMP DWORD PTR DS:[402173],10
    004010BF       7C 36                    JL SHORT reverseM.004010F7                    ;  int numOfGs = 0;
    004010C1    >  8A83 1A214000            MOV AL,BYTE PTR DS:[EBX+40211A]               ;  for(int i = 0; Buffer[i]; i++)
    004010C7    .  3C 00                    CMP AL,0                                      ;  {
    004010C9    .  74 08                    JE SHORT reverseM.004010D3                    ;  if(Buffer[i] == 'G')numOfGs++;
    004010CB    .  3C 47                    CMP AL,47                                     ;  }
    004010CD    .  75 01                    JNZ SHORT reverseM.004010D0
    004010CF    .  46                       INC ESI
    004010D0    >  43                       INC EBX
    004010D1    .^ EB EE                    JMP SHORT reverseM.004010C1
    004010D3    >  83FE 08                  CMP ESI,8                                     ;  if(numOfGs >=8)goto good;
    004010D6       7C 1F                    JL SHORT reverseM.004010F7
    004010D8    .  E9 28010000              JMP reverseM.00401205                         ;  else goto bad;
    Now it is perfectly possibly to get past this without worrying about the higher level principles behind it, but at some point you will want to understand how high-level loops are assembled. The tutorial did not cover this so I will be in this summary. To start off I highly recommend taking a look at these two tutorials: x86 Disassembly/Branches - Wikibooks, collection of open-content textbooks and x86 Disassembly/Loops - Wikibooks, collection of open-content textbooks.

    Now lets break down the code into parts.
    Code:
    004010AE    .  85C0                     TEST EAX,EAX                                  ;  kernel32.BaseThreadInitThunk
    004010B0       75 02                    JNZ SHORT reverseM.004010B4
    004010B2    .  EB 43                    JMP SHORT reverseM.004010F7
    This correlates into a If-Then-Else statement common seen in C++ as:
    Code:
    if(condition)//do something
    else //do something else
    This first thing to realize when converting disassembled logic branches to C++ is that the conditions are always reversed. This means that we treat:
    Code:
    004010AE    .  85C0                     TEST EAX,EAX                                  ;  kernel32.BaseThreadInitThunk
    004010B0       75 02                    JNZ SHORT reverseM.004010B4
    as...
    Code:
    if(eax != 0)// goto reverseM.004010B4
    And the mandatory JMP after JNZ serves as the else

    Code:
    if(eax != 0)// goto reverseM.004010B4
    else //goto badboy
    Now lets try to generate code for the rest of this disassembly. The first step is to identify (action) (initialization) and (conditions)
    Code:
    004010B4    > \33DB                     XOR EBX,EBX                                   ;  initialize to 0
    004010B6    .  33F6                     XOR ESI,ESI                                   ;  initialize to 0
    004010B8    .  833D 73214000 10         CMP DWORD PTR DS:[402173],10                  ;  if(*lpdword >= 16) //condition
    004010BF       7C 36                    JL SHORT reverseM.004010F7
    004010C1    >  8A83 1A214000            MOV AL,BYTE PTR DS:[EBX+40211A]               ;  Buffer[i];
    004010C7    .  3C 00                    CMP AL,0                                      ;  if(Buffer[i] != 0)
    004010C9    .  74 08                    JE SHORT reverseM.004010D3
    004010CB    .  3C 47                    CMP AL,47                                     ;  if(Buffer[i] == 'G')
    004010CD    .  75 01                    JNZ SHORT reverseM.004010D0
    004010CF    .  46                       INC ESI                                       ;  numberOfGs++;
    004010D0    >  43                       INC EBX                                       ;  i++;
    004010D1    .^ EB EE                    JMP SHORT reverseM.004010C1
    004010D3    >  83FE 08                  CMP ESI,8                                     ;  if(numberOfGs >=8)goto good;
    004010D6       7C 1F                    JL SHORT reverseM.004010F7
    004010D8    .  E9 28010000              JMP reverseM.00401205                         ;  else goto bad;
    What we have here is a for loop.

    The initialization is at the top:
    Code:
    004010B4    > \33DB                     XOR EBX,EBX                                   ;  initialize to 0
    004010B6    .  33F6                     XOR ESI,ESI                                   ;  initialize to 0
    The action is in the middle:
    Code:
    004010CF    .  46                       INC ESI                                       ;  numberOfGs++;
    004010D0    >  43                       INC EBX                                       ;  i++;
    Now on to the logic. All loops in disassembly are variations of do-while loops. This is because a while loop is just a do-while with a condition for entering the loop. See: x86 Disassembly/Loops - Wikibooks, collection of open-content textbooks

    We treat these initial conditions just like if statements and therefore the conditions are reversed. The next step is to find the bottom of the loop. In this case it's:
    Code:
    004010D1    .^ EB EE                    JMP SHORT reverseM.004010C1
    Now that we have all the part we can begin rebuilding.
    Code:
    int i = 0;
    int numberOfGs = 0;
    if(*lpdword >= 16)
    {
    	do
    	{
    		if(Buffer[i] == 'G')
    		{
    			numberOfGs++;
    			i++;
    		}
    	}while(Buffer[i])
    }
    
    if(numberOfG's >= 8)//goto good
    else //goto bad
    And this can be consolidated into a for loop:

    Code:
    int numberOfGs = 0;
    if(*lpdword >= 16)
    {
    	for(int i = 0; Buffer[i]; i++)
    	{
    		if(Buffer[i] == 'G')
    		{
    			numberOfGs++;
    			i++;
    		}
    	}
    }
    else //goto bad
    
    if(numberOfG's >= 8)//goto good
    else //goto bad
    Not this may not be exactly right, but the important part is to be able to see highlevel concepts in otherwise monotonous branch statements. It helps to better understand disassembly if you can organize each part into a logical unit.


    Error:
    Lastly there is one error in Lena's tut. She claims that the lpdword parameter named pBytesRead in ReadFile API was the buffer the bytes were read from. this is not true. It is just a DWORD pointer that holds the number of bytes read from the file.

    *This File is included to decrease stress on tuts4you as well as provide a backup in case of server failure.*

    "Every gun that is made, every warship launched, every rocket fired signifies, in the final sense, a theft from those who hunger and are not fed, those who are cold and are not clothed. This world in arms is not spending money alone. It is spending the sweat of its laborers, the genius of its scientists, the hopes of its children. The cost of one modern heavy bomber is this: a modern brick school in more than 30 cities. It is two electric power plants, each serving a town of 60,000 population. It is two fine, fully equipped hospitals. It is some fifty miles of concrete pavement. We pay for a single fighter plane with a half million bushels of wheat. We pay for a single destroyer with new homes that could have housed more than 8,000 people. This is, I repeat, the best way of life to be found on the road the world has been taking. This is not a way of life at all, in any true sense. Under the cloud of threatening war, it is humanity hanging from a cross of iron."
    - Dwight D. Eisenhower

  2. The Following 10 Users Say Thank You to why06 For This Useful Post:

    0xhex (06-29-2013),258456 (01-19-2011),jkcnair (12-20-2012),kibbles18 (05-19-2011),Kuro Tenshi (11-29-2010),Pat55rick (06-30-2014),tdct (06-21-2012),tomtomy1964 (03-16-2016),Toxic Waltz (12-29-2010),Void (11-29-2010)

  3. #2
    Skulhead = hacked.'s Avatar
    Join Date
    Jun 2011
    Gender
    male
    Posts
    521
    Reputation
    10
    Thanks
    225
    My Mood
    Bored
    The read file has to read 46 bytes in a certain adress and puts it in a buffer.
    Why is this? You dont even use it when creating the keyfile.dat

  4. #3
    Hell_Demon's Avatar
    Join Date
    Mar 2008
    Gender
    male
    Location
    I love causing havoc
    Posts
    3,976
    Reputation
    343
    Thanks
    4,320
    My Mood
    Cheeky
    Quote Originally Posted by Skulhead = hacked. View Post
    The read file has to read 46 bytes in a certain adress and puts it in a buffer.
    Why is this? You dont even use it when creating the keyfile.dat
    Probabably to support variable length keyfiles, and doesn't it read 0x46 aka 70 bytes?
    Ah we-a blaze the fyah, make it bun dem!

  5. #4
    Skulhead = hacked.'s Avatar
    Join Date
    Jun 2011
    Gender
    male
    Posts
    521
    Reputation
    10
    Thanks
    225
    My Mood
    Bored
    Quote Originally Posted by Hell_Demon View Post
    Probabably to support variable length keyfiles, and doesn't it read 0x46 aka 70 bytes?
    I thought 46h 70d, but ty.

  6. #5
    uchuu-shi's Avatar
    Join Date
    Aug 2013
    Gender
    male
    Posts
    1
    Reputation
    10
    Thanks
    0
    Shouldn't it be

    Code:
    int i = 0;
    int numberOfGs = 0;
    if(*lpdword >= 16)
    {
    	do
    	{
    		if(Buffer[i] == 'G')
    			numberOfGs++;
    			
                    i++;
    
    	}while(Buffer[i])
    }
    The EBX register gets incremented regardless of the jump of the if-clause.
    Or am I wrong?

  7. #6
    rchayne's Avatar
    Join Date
    Oct 2011
    Gender
    male
    Location
    Australia
    Posts
    1,717
    Reputation
    276
    Thanks
    666
    My Mood
    Psychedelic
    Awesome! Couple of error's, But thank you =)
    https://www.mpgh.net/forum/443-crossf...m-service.html


    [IMG]https://www.danasof*****m/sig/RChayne.jpg[/IMG]

    If I farmed for you!
    If I did a fucking awesome job!


Similar Threads

  1. Lena's Tuts: 04. Basic + aesthetic patching
    By why06 in forum Reverse Engineering
    Replies: 7
    Last Post: 01-27-2011, 08:39 PM
  2. Online Guides to Lena's Tut's
    By why06 in forum Reverse Engineering
    Replies: 2
    Last Post: 12-23-2010, 05:33 AM
  3. Replies: 1
    Last Post: 12-09-2010, 11:43 PM
  4. Lena's Tuts: 03.
    By why06 in forum Reverse Engineering
    Replies: 0
    Last Post: 11-18-2010, 01:29 PM
  5. Replies: 4
    Last Post: 08-07-2010, 05:29 PM