Ollydbg entry series (4)-memory breakpoint

Source: Internet
Author: User

Title: [original] ollydbg
Entry series (4)-memory breakpoint
Author: ccdebuger
Time:
2006-02-15,23: 22: 00
Link:
Http://bbs.pediy.com/showthread.php? T = 21378

Ollydbg entry series (4)-memory breakpoint

Author: ccdebuger

Remember the content in the ollydbg entry series (III)-function reference in the previous article? In that articleArticleAfter analysis, we find that an ESI register value does not know where it is generated. To find out this problem, we must find the calculation part that generates this ESI value. Today, our task is to use the ollydbg memory breakpoint function to find out how this value is calculated. Objectives of this AnalysisProgramOr the crackme in the previous article. I will not upload any more attachments. I can use the attachments in the previous article. Let's start:
Remember the key points we mentioned in the previous article.Code? Review:

00401323 |. e8 4c010000 call ; getwindowtexta
00401328 |. e8 a5000000 call crackhea.004013d2; key: Press F7.
0040132d |. 3bc6 CMP eax, ESI; comparison
0040132f |. 75 42 jnz short crackhea.00401373; otherwise it will be finished

we re-use ollydbg to load the target program. F9 runs to the place where the above Code is located (should the breakpoint you set last time not be deleted ?), Let's look up and see if we can find the value assigned in the ESI register. Haha, it turned out to be nearby:
we now know that the ESI register value is sent from the memory address 40339c, when is the data in the memory address 40339c generated? Note that DS: [0040339c] = 9fcf87aa is displayed in the information window. You may be DS: [0040339c] = XXXXXXXX, XXXXXXXX indicates other values, which is different from 9fcf87aa. Let's take a look at the following operations in the data window:
we can see that the value of the memory address 40339c already exists, which means it is too early. What should we do now? Let's take a look at it. The program calculates this value and writes it in this memory address. If we can interrupt the ollydbg when the program starts writing something to this memory address, isn't it possible to know how the target program calculates this value? Click debug in the ollydbg menu-> Start again, or press the CTR + F2 key combination (you can also click the icon with two solid left arrows on the toolbar) to reload the program. In this case, a dialog box "the process is still in the active state" appears. (You can remove the preceding "warning when terminating the active process" under the Security Tab Of the debugging option, in this case, this dialog box will not appear next time.) ask if we want to terminate the process. Here we select "yes" and the program is reloaded. We will stop at the following sentence:

00401000>/$ 6a 00 push 0; pmodule = NULL

now we have to set a memory breakpoint. In ollydbg, we generally use memory breakpoints including memory access and memory write breakpoints. Memory Access breakpoint refers to the interruption when the program accesses the memory address we specified in the memory. The memory write breakpoint refers to the interruption when the program writes something to the memory address we specified. For more information about breakpoints, refer to the topic 7-> basic knowledge-> breakpoint skills-> breakpoint principles. This article by lenus, how to combat one of hardware breakpoints-debugging registers, can also see this post: http://bbs.pediy.com/showthread.php? Threadid = 10829. Based on the specific program we are debugging, we use the memory to write breakpoints. Do you still remember the 40339c memory address I told you to remember? Now we need to use it. In the ollydbg data window, click left and right-click. A menu shown in is displayed. Select the convert to-> Expression (you can also click the data window and press the CTR + G key combination ). For example:
now a dialog box is displayed:
in the above edit box, enter the memory address 40339c, click OK. The data window is displayed as follows:
we can see that there is no content in the memory at the beginning of the 40339c address. Now, in the Hex data or ASCII column behind the 40339c address, press and hold the left button, drag and drop, and select a segment. The memory breakpoint feature is that no matter how many bytes you select, The ollydbg will allocate a 4096-byte memory zone. Here I will choose four bytes starting from the 40339c address, mainly to let you know how to manage the hardware breakpoint in advance, because the hardware breakpoint can only select up to four bytes. The selected part is displayed in gray. After the selection, release the left mouse button and right-click the selected gray area:
after the operation, we have set the memory breakpoint (note that the memory breakpoint is only valid in the current debugging process, that is to say, if you re-load the program, the memory breakpoint will be automatically deleted. The memory breakpoint can only have one at a time. That is to say, you cannot set multiple breakpoints at the same time as pressing the F2 key ). Now press the F9 key to run the program. Oh, ollydbg is disconnected!

7c932f398808 mov byte ptr ds: [eax], Cl; this is the first time that we have disconnected
7c932f3b 40 Inc eax
7c932f3c 4f dec EDI
7c932f3d 4E dec ESI
7c932f3e ^ 75 CB jnz short ntdll.7c932f0b
7c932f40 8b4d 10 mov ECx, dword ptr ss: [EBP + 10]

The above is the code in the Disassembly window after our interruption. If you are using another system, such as Win98, it may be different. It doesn't matter. This is not the key. Let's take a look at the airspace, which was originally in Ntdll. dll. System airspace. Now we need to consider returning to procedural airspace. Before returning, let's take a look at the data window:

Now, go to the Disassembly window, right-click and choose breakpoint> Delete memory breakpoint from the pop-up menu, so that the memory breakpoint is deleted.

Now let's press the Alt + F9 key combination, and we come to the following code:

00401431 |. 8d35 9c334000 Lea ESI, dword ptr ds: [40339c]; location after ALT + F9 is returned
00401437 |. 0fb60d ec334000 movzx ECx, byte ptr ds: [4033ec]
0040143e |. 33ff xor edi, EDI

Let's flip the Disassembly window up. Oh, it turns out to be under the code we analyzed in the previous article?

Now we have set a breakpoint by pressing F2 on the command at the 0040140c address. Now we press the CTR + F2 key combination to re-load the program and press the F9 key to run the program, we will be interrupted at the breakpoint at the 0040140c address:

0040140c/$60 pushad
0040140d |. 6a 00 push 0;/rootpathname = NULL
0040140f |. E8 b4000000 call <JMP. & kernel32.getdrivetypea>; \ getdrivetypea
00401414 |. A2 ec334000 mov byte ptr ds: [4033ec], Al; disk type parameter memory delivery address 4033ec
00401419 |. 6a 00 push 0;/pfilesystemnamesize = NULL
0040141b |. 6a 00 push 0; | pfilesystemnamebuffer = NULL
0040141d |. 6a 00 push 0; | pfilesystemflags = NULL
0040141f |. 6a 00 push 0; | pmaxfilenamelength = NULL
00401421 |. 6a 00 push 0; | pvolumeserialnumber = NULL
00401423 |. 6a 0b push 0b; | maxvolumenamesize = B (11 .)
00401425 |. 68 9c334000 push crackhea.0040339c; | volumenamebuffer = crackhea.0040339c
0040142a |. 6a 00 push 0; | rootpathname = NULL
0040142c |. E8 a3000000 call <JMP. & kernel32.getvolumeinformationa>; \ getvolumeinformationa
00401431 |. 8d35 9c334000 Lea ESI, dword ptr ds: [40339c]; send the name of the volume in the partition where the crackme program is located to ESI
00401437 |. 0fb60d ec334000 movzx ECx, byte ptr ds: [4033ec]; the disk type parameter is sent to ECx
0040143e |. 33ff xor edi, EDI; clear EDI
00401440 |> 8bc1 mov eax, ECx; the disk type parameter is sent to eax
00401442 |. 8b1e mov EBX, dword ptr ds: [esi]; send the volume name as a value to EBX
00401444 |. f7e3 Mul EBX; the disk type parameter value is multiplied by the volume name value by the circular decrease.
00401446 |. 03f8 add EDI, eax; each calculation result plus the last calculation result is saved in EDI
00401448 |. 49 dec ECx; the disk type parameter is used as the number of cycles, decreasing in turn
00401449 |. 83f9 00 CMP ECx, 0; Determine whether the calculation is complete
0040144c |. ^ 75 F2 jnz short crackhea.00401440; Continue
0040144e |. 893d 9c334000 mov dword ptr ds: [40339c], EDI; send the calculated value to the memory address 40339c, Which is the value we will see in ESI later
00401454 |. 61 popad
00401455 \. C3 retn

Through the above analysis, we know the basicsAlgorithmUse the getdrivetypea function to obtain the disk type parameter, and use the getvolumeinformationa function to obtain the volume tag of the partition where the crackme program is located. For example, if I put this crackme program under the F: \ OD tutorial \ crackhead \ directory, and the volume set on disk F is game, the game is obtained here, the ASCII code is "47414d45 ". But we found a problem: If the hexadecimal code at address 40339c we saw in the data window is "47414d45", that is, "game ", however, after the mov EBX, dword ptr ds: [esi] command at address 00401442, we found that the value of EBX is "454d4147 ", the above "47414d45" is reversed. Why? If you know about the storage methods of X86 series CPUs, it is easy to understand here. We know that "game" has four bytes, namely, the ASCII code is "47414d45 ". Let's take a look at the situation in the data window:

0040339c 47 41 4D 45 00 00 00 00 00 00 00 00 00 00 game ............

we can see that the memory address 40339ch to 40339fh is stored in 47 41 4D 45 sequentially.
For example:
the system storage principle is "high, low, and low", that is, the low bytes are stored in the byte unit with a low address, high bytes are stored in the byte units with a higher address. For example, a word is composed of two bytes, such as 12 34. The high byte here is 12, and the low byte is 34. The preceding command mov EBX, dword ptr ds: [esi] is equivalent to mov EBX, dword ptr ds: [40339c]. Note that DWORD is a dual character consisting of four consecutive bytes. When we get the content in the dual-cell with the address of 40339c, we should get "454d4147", that is, the value from the high byte to the low byte order. Therefore, the mov EBX, dword ptr ds: [esi] Command sends the value starting from the address 40339c to EBX, so we get "454d4147 ". Now, let's talk about the algorithm of this program. We have already mentioned the number of cycles using the disk type parameter, and then the reverse order of the ASCII code of the volume value as the value. With these two values, the computation starts. Now we take the disk type value as N, and the reverse sequence value of the ASCII code of the volume value as a, and the final result as B. The calculation process is as follows:
the first time: B = A * n
second time: B = A * (N-1) + B
third time: B = A * (N-2) + B
...
N times: B = A * 1 + B
the formula is B = A * [n + (n-1) + (n-2) +... + 1] = A * [N * (n + 1)/2]
do you still remember our analysis in the previous article? Read this sentence:

00401405 |. 81f6 53757a79 xor esi, 797a7553; the values in ESI are different from those in 797a7553h or

The final difference between B and 797a7553h is the real registration code. As long as you know something about programming, this registration machine is very easy to write. If compilation is used to write this registration machine, it will be simpler, and a lot of content can be copied directly.
It's almost the same now. Let's talk about a few things at last:
1. The above two API functions are used: getdrivetypea and getvolumeinformationa. I will not talk about the specific usage of these two functions. You can check msdn. Pay attention to the order in which function parameters are transmitted, that is, the call conventions. Let's take a look at it here:

00401419 |. 6a 00 push 0;/pfilesystemnamesize = NULL
0040141b |. 6a 00 push 0; | pfilesystemnamebuffer = NULL
0040141d |. 6a 00 push 0; | pfilesystemflags = NULL
0040141f |. 6a 00 push 0; | pmaxfilenamelength = NULL
00401421 |. 6a 00 push 0; | pvolumeserialnumber = NULL
00401423 |. 6a 0b push 0b; | maxvolumenamesize = B (11 .)
00401425 |. 68 9c334000 push crackhea.0040339c; | volumenamebuffer = crackhea.0040339c
0040142a |. 6a 00 push 0; | rootpathname = NULL
0040142c |. E8 a3000000 call <JMP. & kernel32.getvolumeinformationa>; \ getvolumeinformationa

Compare the comments automatically added by the ollydbg after the code above with the function prototype in msdn:
Bool getvolumeinformation (
Lpctstr lprootpathname, // address of root directory of the file system
Lptstr lpvolumenamebuffer, // address of name of the volume
DWORD nvolumenamesize, // length of lpvolumenamebuffer
Lpdword lpvolumeserialnumber, // address of volume serial number
Lpdword lpmaximumcomponentlength, // address of system's maximum filename Length
Lpdword lpfilesystemflags, // address of file system flags
Lptstr lpfilesystemnamebuffer, // address of name of File System
DWORD nfilesystemnamesize // length of lpfilesystemnamebuffer
);

What should we see? Function call is to first press the last parameter to stack, and the parameter pressure stack order is from the back to the front. This is a common stdcall call convention.
2. the mov byte ptr ds: [4033ec] at the first 00401414 address. The comment added after the Al command is "disk type parameter sends memory address 4033ec ". Why? Let's take a look at the previous sentence and this sentence together:

0040140f |. E8 b4000000 call <JMP. & kernel32.getdrivetypea>; \ getdrivetypea
00401414 |. A2 ec334000 mov byte ptr ds: [4033ec], Al; disk type parameter memory delivery address 4033ec

The command at address 0040140f calls the getdrivetypea function. Generally, the returned values after the function is called are stored in eax, so the mov byte PTR Ds at address 00401414: [4033ec], Al is the return value. Check msdn to know that the return values of the getdrivetypea function include the following:

Value Meaning returned value in eax
Drive_unknown the drive type cannot be determined. 0
Drive_no_root_dir the root directory does not exist. 1
Drive_removable the disk can be removed from the drive. 2
Drive_fixed the disk cannot be removed from the drive. 3
Drive_remote the drive is a remote (network) Drive. 4
Drive_cdrom the drive is a CD-ROM drive. 5
Drive_ramdisk the drive is a RAM disk. 6

The above "value returned in eax" is added by me, and 3 is returned here, that is, the disk cannot be deleted from the drive.
3. By analyzing the algorithm of this program, we find that this registration algorithm has a vulnerability. If my partition does not have a volume label, the volume value is 0, and the final registration code is 797a7553h, that is, decimal 2038068563. If your volume label is the same as mine, and the disk type is the same, the registration code will be the same, and it cannot be a single machine.

Thank you for pointing out the error in this article!

--------------------------------------------------------------------------------
[Copyright notice] This article is purely a technical exchange. repost the article to indicate the author and keep it complete. Thank you!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.