C Modify
statement
Individuals can freely reprint this article, but should maintain the integrity of the original text and inform me; if the business reprint first contact me first.
There is no clear or unclear note that this article is completely correct, read and use this article is your own choice, I am not responsible.
If you find that this article has a wrong place, please give me a pointed out; if you don't understand anything, please give me a given.
Opinions, suggestions and proposed issues are best written in my home page http://llf.126.com's message.
Foreword
I wrote two articles about the font size of the non-resource format of the C program, and Wei Communications, I don't understand it, I have to talk about it, and the revision of this non-resource format, actually built in modification On the basis of the program, and because the programmer is different, the resulting program sets the font size method may also be a thousand variable, and the compiler is optimized, so there is no fixed format, not It is most likely to complete the modification without understanding the assembly language, in addition, the use of Windows processing fonts and TRW2000 can also be understood.
Based on the above reasons, I first talked about some things about the font size, API and TRW2000, and then tell the way of modifying the Opera font size. I hope that everyone will see the modification of the Opera in the case of understanding the contents of the previous.
However, this article cannot tell too much content. If you don't understand the front part, you can look at it several times. It is best to see some other books that tell the content of this, definitely be said here. Clear and comprehensive, and I am not big in this regard. More detailed content.
Word number
In Windows programming, there are many units of coordinates.
One is our most familiar pixel (Pixel), the pixel represents the physical coordinates, such as the 640x480, 800x600 referred to as usually said.
Another important thing is pounds, it is a logical coordinate, which is a unit of printing, approximately 1/72 inches, defined in Windows 1/72 inches.
There is also a more important thing (Twips), VB is default, using a stone as its unit, 20 is equal to 1 pound, so 1 is 1/1440 inches.
There are also several units, representative centimeters, millimeters, and I don't say it here.
Because Windows does not know the size of our monitors, it is the size of inches through our settings. Ok, let's take a look at the settings about the font size in Windows.
In the Display Properties dialog box, you can set the size of the font, but only two settings are small fonts, the other is a big font. Among them, the small font indicates 96DPI, while the big font represents 120DPI. Small font is the default option, while the big font is when the screen resolution selected by the user is too large (such as 1600x1200), in order to avoid the font too small, it is not clear. In addition, the user can also set the resolution of the font, but the value is not necessarily.
We often say "Song Body, 9", indicating that the unit is actually pound, that is, 9 pounds of Song.
Let's call. At the small font, the resolution is 96dpi, that is, the one inch can display 96 pixels; 9 pounds are 1/8 inches, so 96/8 = 12 pixels. In other words, the font we usually see is the font of this 12x12 o'clock.
In addition, when the big font, the resolution is 120dpi, 9 pounds are 1/8 inches, so 120/8 = 15, that is, when the big font, the displayed 9-pound font is actually a font of 15x15 o'clock. In VB, VC or Delphi, after the form is set, the form is automatically adjusted with the size of the size or a small font, because they use logical units. By default, it is a mite for VB, which is pound for VC and Delphi.
CreateFont
Last said, if the font is not set, it will be displayed as "System, 12", so as long as it is a program that is too small, it will be set.
There are two functions set in Windows, one is CREATEFONT, one is CREATEFONTINDIRECT.
Where the definition of CREATEFONT is as follows:
HFONT CREATEFONT
Int Nheight, // Logical Height of Font
INT NWIDTH, / / LOGICAL AVERAGE CHARACTER WIDTH
INT Nescapement, // Angle of escapement
Int norientation, // base-line Orientation Angle
Int fnweight, // font weight
DWORD FDWITALIC, // Italic Attribute Flag
DWORD FDWUNDERLINE, // underline Attribute Flag
DWORD FDWSTRIKEOUT, / STRIKEOUT Attribute Flag
DWord Fdwcharset, // Character Set Identifier
DWORD fdwoutputPrecision, // output precision
DWORD fdwclipprecision, // clipping precision
DWORD fdwquality, // output Quality
DWord fdwpitchchandfamily, // pitch and family
LPCTSTR LPSZFACE / / POINTER TO TYPEFACE NAME STRING
);
There are three types of parameters: int, dword and lpctstr. INT and DWORD are four-by-word integer, LPCTSTR is also four-by-word integer, but it is a pointer, processing method, and the former.
Among them, the first NHEIGHT is the font size we have to modify. However, the value here is actually used, so it is recommended to set the font size in MSDN.
NHEIGHT = -muldiv (Pointsize, GetDeviceCaps (HDC, Logpixelsy), 72);
This is to convert pounds into pixels, and become negative. For why Microsoft define a negative number is normal, I don't know clear, but there is no relationship, remember to use a negative number.
In addition, fdwcharset is a language, and LPSZFACE is a font name and it is also our concern. However, you can make the font name empty so that Windows automatically finds the default font, then there is no need to modify the language.
The definition of CREATEFONTINDIREC is as follows:
HFONT CREATEFONTINDIRECT (Const logfont * LPLF // Pointer to Logical Font Structure
);
The parameters transmitted here are a pointer, pointing to a logfont structure, the LogFont is defined as follows:
Typedef struct taglogfont {// lf
Long Lfheight;
Long lfwidth;
Long LFESCAPEMENT;
Long Lirting;
Long LfWeight;
BYTE LFITALIC;
BYTE LFUNDERLINE;
Byte lfstrikeout;
BYTE LFCHARSET;
BYTE LFOUTPRECISION;
BYTE LFCLIPPRECISION;
BYTE LFQUALITY;
BYTE LFPITCHANDFAMILY;
Tchar LFFACENAME [LF_FaceSize];
Logfont;
This structure and the structure of the font block of the VB are some similar. If it is integrally read, the modified memory is the same, but generally not overall, but a one of the programs that compile this. It is also together, but because it is a load, the order of the four bytes of the long-type value and the actual order in the memory are the opposite (see "Unicode Addition") . However, there are many cases, the font structures are not initialized in the same place, such a program, there will be no more than the value of the value.
Note that the type of font name LFFCACename is TCHAR, indicating that if the program is compiled into a Unicode format, the font name will use Unicode. In addition, the type of CreateFont's parameter-based name LPSZFACE is LPCTSTR, pay attention to the "T" in the middle, which means that this is also a pointer that can be compiled into Unicode. Of course, the compilation option is different, the function name will change. If compiled into ASCII, createFont will be CREATEFONTA, if compiled into unicode, it will become createFontw.
Windows 95/98 supports all ASCII functions and a very small Unicode function, internal use ASCII mode processing; Windows NT / 2000 supports all ASCII functions and all Unicode functions, using all Unicode mode processing.
(Although it is not related to this question, WINDOWS 95/98 supports a small amount of Win32 function (Windows 32-bit function, no Windows 3.2 function!), And Windows NT / 2000 supports all Win32 functions. This is why Windows Many of the NT can handle Windows 98 can't process reasons - such as save the edited resource back the executable.)
API call agreement
Almost every language has functions, and as a function, there is a parameter. Generally, the passage of the parameters is through the stack (the stack is a first in the following structure, using PUSH press, use PUSH And POP must be used), there are two different processing methods.
One way is to press the parameters into the stack in the original order, and then use the Call instruction call function, and the function uses the POP pop-up stack and then processes the parameters. This method is advantageous for the caller because the call is advantageous because the calorie is advantageous for the caller. In the contrary, the other method is to press the parameters into the stack in the reverse sequence, and then use the CALL instruction call function, and the function uses the POP pop-up stack and then processes the parameters. So this method is advantageous for the caller because the parameters of the positive order obtained by the modified function.
The C language and PASCAL languages use these two ways, and the call mode of Windows is the same as the PASCAL. Therefore, when the previous C program is written in the Windows program, you need to use the keyword PASCAL to specify the use of the PASCAL call rule; now generally does not use the PASCAL key Word, but use __stdcall setup, indicating that it is a standard call. This is now called standard call is the second way - the reseller stack.
This method of resetting stack does have a good time. Because the behavior of the stack is compiled by the compiler, although it is troubles, it is only compiled; and the behavior of the slum is dynamic, the use of positive order is more convenient, and the speed is faster.
For example, CREATEFONT calls are like the following:
Push Lpszface
Push FDWPITCHANDFAMILY
Push fdwquality
Push fdwclipPrecision
Push fdwoutputPrecision
Push fdwcharset
Push fdwstrikeout
Push fdwunderline
Push fdwitalic
Push Fnweight
Push Norientation
Push Nescape
Push nwidth
Push nheight
Call CreateFont
Note that pseudo codes are written here, and the true assembly code cannot be read well, and there may be other code between PUSH, but as long as it knows the number and parameters of the parameters that need to be pressed into the stack. We can still find out what the parameters of each press-in.
Contact TRW2000
Because the TRW2000 is unlikely screenshots, I made a form of examples as the following:
Space memory data display area of register and its value
Disclosure code display area stack data display area code display command display area
Note that this is just a normal case, in fact, in fact, the user can switch the size displayed by each area.
"Register and its value display area" display register and its value, its formats have a lot of registers, because TRW2000 will display all registers, I will not listed here.
"Memory Data Display Area" is used to display memory data. To display memory data, there are four commands: D, DB, DW, DD. The DB refers to the memory data according to byte format; DW refers to the memory data according to the format of the double-byte integer; DD indicates memory data in the format of the four-byte integers; and the D command displays memory data using the current format. The displayed is the hexadecimal value. Because the Inter CPU takes a high level behind, the data and single-byte format of the double-byte and four-byte format are in reverse. (See "Unicode Replenishment")
"Anti-assembly code display area" shows the disassembly code. Here is our most concerned, because the assembly code of the last example of the last section will be displayed here, and the analysis of the code is the key to our modification of the font size.
"Stack Data Display Area" Displays stack data. Here is the focus of our attention. As mentioned in the previous section, the parameters are passed using the stack, so the data here is to pass to the function. Its format is a line display two data, and the second data is the parameter, and the first data is a pointer to the second data. Therefore, it is actually displaying a line of data, and the data that is pressed is on top. Because Windows uses a positive semaphore, the data in the stack is first, second, three ... parameters from top to bottom when running to the Call statement. "Display of the code" display code location area. In the two articles, I often say "return to the XX code area", I know here. For example, the CREATEFONT function is a GDI function. If you inside CreateFont, "GDI! XXXXXXXX" is displayed here, where xxxxxxxx is indicated by the current code; if you are in the code area of Opera, you will show "Opera! Xxxxxxxx" .
"Command Display Area" is where you enter and display the command, there is nothing to say.
Also, you have to talk about several commands we often use in TRW2000.
"F5" or "g" command. The effects of these two ways are the same, all of which are running procedures.
"F6". This command is used to switch the area where the direction key is located. By default, the arrow keys are in the command area. At this time, use the arrow keys to control the page pages of the command area; press "F6" once, in the code area, at this time, you can use the direction keys to flip the code; then press "F6" Then return to the command area.
"Bpx" command. Interrupt command, specify where to run the program, can be the address, or the API function, the following format is correct: "BPX 00441122", "BPX CreateFonta". ("F9" is also a "bpx" instruction, but "F9" cannot define the API function, only the current behavior breakpoint can be set)
"F8" and "f10". These two commands are used to track the operation of the program, and the difference is that if the CALL code is encountered, "F8" is tracked to the internal call of this call, and "F10" runs this call and tracks the first one after the call returns. The statement is on.
"R" command. This command is used to modify the value of the register. For example, the last Push statement is "push eax", then modify the value of the EAX register before this statement is executed, and the value to be pressed into the stack is also modified.
"E" command. This command is used to modify the memory, which can be written as "e xxxxxxxx", where "xxxxxxx" represents the address, but it can also be a register name, such as "e ESP" because the register ESP is a stack pointer, so it represents the data modified the stack; You can write a separate "E", indicating that modifying the memory data currently displayed.
Actual combat Opera
The old saying that "three paper no", today discovered that this is not easy to achieve. :) But fortunately, we really want to modify the font size.
The example used here is the Opera 4.0 Beta 5 of Wei Jie. After Han, the button of the main form is too small, not the "Song, 9" we often see, so the main focus is the reminder of the font. For prompt fonts, if the program calls the prompts provided by Windows, use the default prompt font size display, which is generally "Song, 9" (the user can modify the font number used by the prompt), so Opera is definitely not Call the Windows function, but it is realized.
First check the Opera.exe's function import table first, found that it used CreateFonta and use CreateFontIndirecta, which is really disgusting, just take the CreateFonta. Run the TRW2000, select Opera.exe, point LOAD, now there is a TRW2000 debug window, type the command "BPX CreateFonta", which is interrupted when the program calls the createFonta function. Then press "F5" to run the program.
prompt:
If the original program is not run before using the TRW2000 to transfer, it is definitely not in the disk cache, and the speed of TRW2000 is very slow from the disk from the disk. So it is recommended to run the original program before running the TRW2000, then turn it off, and then run the TRW2000 to transfer program, the speed is much faster. TRW2000 is very important to optimize this in this respect.
The program interrupts at the entrance of CreateFonta, and the "display of the code is displayed", it can be seen in the GDI module, when typing "PModule" instructions, the program runs back to the Code area of Opera, you can see the previous one The call is CREATEFONTA, look up the PUSH statement, find the following code:
Offset byte code assembly code
015F: 00441101 FF7544 PUSH [EBP 44]
015F: 00441104 50 PUSH EAX
015F: 00441105 0FB6453C MOVZX EAX, Byte PTR [EBP 3C]
015F: 00441109 50 Push EAX
015F: 0044110A 0fb64538 MOVZX EAX, Byte PTR [EBP 38]
015F: 0044110E 50 PUSH EAX
015F: 0044110F 0fb64534 MOVZX EAX, Byte PTR [EBP 34]
015F: 00441113 50 Push EAX
015F: 00441114 0FB64530 MOVZX EAX, Byte PTR [EBP 30]
015F: 00441118 50 PUSH EAX
015F: 00441119 0FB6452C MOVZX EAX, Byte PTR [EBP 2C]
015F: 0044111D 50 PUSH EAX
015f: 0044111e 0fb64528 MOVZX EAX, Byte PTR [EBP 28]
015F: 00441122 50 Push EAX
015F: 00441123 0FB64524 MOVZX EAX, Byte PTR [EBP 24]
015F: 00441127 50 PUSH EAX
015f: 00441128 FF7520 Push [EBP 20]
015F: 0044112B FF751C PUSH [EBP 1C] 015F: 0044112E FF7518 PUSH [EBP 18]
015F: 00441131 FF7514 PUSH [EBP 14]
015F: 00441134 FF7510 PUSH [EBP 10]
015F: 00441137 FF15F8005300 Call GDI32! CreateFonta
015F: 0044113D 8BF0 MOV ESI, EAX
This code is very similar to the code I do above, but some MOVZX instructions are inserted. After the offset is byte code, the "Code On" instruction is used in TRW2000 will only be displayed, and I will write it in order to facilitate. Note that the segment offset running Opera on your machine may differ from "015F" here.
In general, should now press "F6" to the code area, stopped on "Call GDI32! CreateFonta" at 015F: 00441137 ", press" F9 "to set breakpoints so that it can be easily interrupted when running However, it may be that there is too much job to do when Opera is exited, so if you don't turn off the TRW2000 first, Opera exits very slow, anyway, I can't wait until it is normal, I have to restart.
Due to the above reasons, "00441137" is recorded so that the breakpoint is set when the next runtime. Then press "F5" to run, no interrupt, so only the CreateFonta function is called when Opera starts.
Now turn off the TRW2000, then turn off Opera, then run the TRW2000, then select Opera.exe, press LOAD to transfer, press "F10", let the code are in the area where Opera is located, type "BPX 00441137", this "00441137" is The address of the CreateFonta function just recorded, then press "F5" to run the program.
When the TRW2000 debug form appears again, the discovery code is just running to "Call GDi32! CreateFonta", is preparing to call this function, then look at the stack display area, find the top data is "fffffff5", that is, decimal - 11, we already know that at least -12 can be displayed normally, we may change more, so type "DD ESP" to display the stack data in a four-byte manner, then type "E ESP" to modify the stack, now the cursor is in memory The data area, type "fffffff0", enter, see the stack top data of the stack has been changed to "fffffff0", press "F5" to run, enter the main interface of Opera, now put the mouse on the button, you can see The button tips have been displayed very much, so that only half of the Chinese characters can be displayed. So we know that this created font created by this createfonta is used for button prompts, and other CreateFontIndirecta functions are not checked. (This is not to check that you don't have to check, I have found the ten CreateFontIndercta functions called when starting, and modified the parameters of all the ten functions, and confirmed that not the CreateFontIndirecta letter, and then check the CreateFonta function. Ok: () Ok, now I don't change it to "fffffff4" and change to "fffffff0". Because it is changed to "fffffff4" no effect, why? Because Opera uses a very strange font It seems like "Helv", if it is interrupted at "00441104", then use "DD * ESP" to see it. This font shows that the normal 12-pixel font we expects to be expected, so It is necessary to modify the word name.
I am lazy, so I didn't find the program when I changed "[EBP 44]" ([EBP 44] "in the C language (EBP 0x44), indicating the value indicated by the pointer), Just modify the parameters of pressing stack, change "[EBP 44]" to "0", which is an empty pointer, because there is no specified font, Windows uses the default Song to display.
I am lazy, I haven't going to find when the program modified [EBP 10], I directly fed -12 to the stack and used this method for the modification of the executable.
Therefore, finalization of the executable is to modify "Push [EBP 44]" to "Push Byte 00", modify "Push [EBP 10]" into "Push Byte -0c".
The byte code of "Push [EBP 44] is" FF7544 "," Push [EBP 10] "byte code is" ff7510 "; and" Push Byte 00 "byte code is" 6A00 "," The byte code of Push Byte -0c is "6AF4". More than two bytes here, there is no relationship, there is a NOP instruction in the assembly instruction. It is an empty directive. The CPU does not dry when encountering this instruction, just as a filled surplus, its byte code Yes "90".
Therefore, the final revision is this: Find "FF7544500FB6453C500FB64538" and modified the beginning "FF7544" to "6A0090"; find "FF7510FF15F80053008BF0" and modify the beginning of "FF7510" into "6AF490". Battle WinRAR
As a modified font size, it is not very possible without using it, but it is not necessary to use TRW2000. Let me introduce an example of modifying the font font size using W32DASM disassembly.
W32DASM is a static disassembly tool, that is, it is based on the anti-appointment code obtained for the analysis of the executable, the original program is actually not running, so that there is no relationship with the code in the program. , Because the original procedure does not need to operate, it is simple to operate, but it is a shortcoming that the status of registers and memory compared to dynamic disassembly is not known to run to a statement. However, each of these two methods has a good place, which is the completion of complement. (My homepage has the download of W32DASM 8.93)
If the WinRAR file is written, the main form will have a comment form appear when this file is opened, and the font is not small, but if it is a Chinese comment, it always seems to be twisted, so it is very uncomfortable, so Use it to do an example.
Run W32DASM, have its main form, select menu "Disassembler" -> "Open file to disassemble ..", the file selection box, select "WinRar.exe", then W32DASM will analyze the program, this process takes some time, wait until you come After all, select the menu "Disassembler" -> "Save Disassembly Text File and Create Project File", save the file dialog box, we save the file, then exit W32DASM.
At this time, there will be two files "WinRAR.PRJ" and "WinRAR.Alf" in the catalog of WinRAR. "WinRAR.PRJ" is a W32DASM project file, we don't care, we care about the anti-assessment "WinRar.alf" file, but this file is really large, there is 8.22MB.
Now, use a text editor that opens large files and very fast, open "WinRAR.Alf", find "createfont". The first found is this:
AddR: 000d9b00 hint (0000) Name: CreateFonta
This is the data imported in the function, indicating that WinRAR imports the CreateFonta function. Continue to find, the following is this:
* Reference to: gdi32.createfonta, ORD: 0000H
This sentence that uses "*" begins with W32DASM to joining the user, not assembly code, but it indicates that the next statement is executing CreateFonta, so we look at it, because CreateFonta has 14 parameters, so Find 14 PUSH statements up:
* Possible StringData Ref from Data Obj -> "MS Sans Serif"
|
: 0040720D 68274E4600 Push 00464E27
00407212 6A00 push @ 00000000000020040300 0000-00-00 0000-00-00 0000-00-00
00407216 6A00 PUSH 00000000
00407218 6A00 Push 00000000
0040721A 6A00 Push 00000000
0040721C 6A00 Push 00000000
0040721E 6A00 Push 00000000
00407220 6A00 Push 00000000
* Possible Reference to string resource id = 00700: "? 遄"
|
00407222 68BC020000 PUSH 000002BC
00407227 6A00 Push 00000000
00407229 6A00 Push 00000000
: 0040722B 6A00 Push 00000000
* Possible Reference to string resource id = 00244: "僢 (冐 ??"
|
: 0040722D 6AF4 PUSH FFFFFF4
* Reference to: gdi32.createfonta, ORD: 0000H
|
: 0040722F E84BAA0500 CALL 00461C7F
This time call is really a one, and the pseudo code written above can be said to be a touch. We can see that the first line is a prompt. "The address used by the following statement may be the 'MS Sans Serif' pointer", which is too obvious, it is indeed. However, the second prompt says "The following may be the address of the string resource", this is wrong, because we know, the so-called "push 000002bc" is crushing the character width, this 2BC is 700, that is, indicate It is a bold. The third prompt is not right, we know that "push ffffff4" is embedded in the font, which means that 12 pixels are created.
Ok, we have modified, and it may be changed. In the above code, I use green to march all byte codes, which is the character stream that will appear in the executable file, so we open WinRar.exe with a hex editor, look for "6af4e84baa0500 ", Find, and change the" 6AF4 "to" 6AD8 ". Run WinRAR and open a note-free file, found that the font of the comment box has not changed, so close winRAR, continue to find "createfont" in the "WinRar.alf" file.
10 "createfont" can be found in "WinRAR.Alf", the first one is the function import table, the rest is the prompt of W32DASM. Every time we check a "createfonta" call, we tried to modify its font size and run the WinRAR test until we modify the third "createFonta" called found, we test the font of the comment box to become bigger, And very big, so scary. :), and the whole process of the third "CreateFonta" call is as follows: * Possible StringData Ref from Data Obj -> "Terminal"
|
0041230D 689A594600 PUSH 0046599A
00412312 6A01 PUSH 00000001
00412314 6A00 PUSH 00000000
00412316 6A00 PUSH 00000000
00412318 6A00 PUSH 00000000
: 0041231A 68FF000000 PUSH 000000FF
0041231F 6A00 Push 00000000
00412321 6A00 PUSH 00000000
00412323 6A00 PUSH 00000000
* Possible Reference to string resource id = 00500: "?? 剠 xe @ 圅"
|
0041235 68F4010000 Push 000001F4
0041232A 6A00 Push 00000000
0041232C 6A00 Push 00000000
0041232E 6A00 Push 00000000
* Possible Reference to string resource id = 00244: "僢 (冐 ??"
|
00412330 6AF4 PUSH FFFFFF4
* Reference to: gdi32.createfonta, ORD: 0000H
|
: 00412332 E848F90400 CALL 00461C7F
what! WinRAR's call is really specific. Ok, we see it, in this call, the font size is "F4", there is no error, and the font name is "Terminal", a strange font, no matter how to say, let it change it first.
Find "689A5946006A01" and modified the "689A594600" to "6800000000" or "6A00909090". (68 is also a PUSH statement. 6A is pressed into single-byte integers, 68 is pressed into four-by-one integer)
Then run, the font is still very strange, continue to modify. The following "6A01" is pressed into "fdwpitchandfamily", do not know what, anyway, as long as it is changed to 0, Windows will use the default value, so "6A01" is changed to "6A00". Run the program again, the font is normal.