当前位置:网站首页>[reverse primary] Unique

[reverse primary] Unique

2022-07-06 17:23:00 TiggerRun

become an independent school

stem

Title address :https://ctf.pediy.com/itembank.htm
 Insert picture description here
It's a verifier , It can also be called a registration machine .
The meaning of the title is to let us get users :CTFHUB Of Code

0x1 Check the shell

 Insert picture description here

0x2 OD debugging

My first thought is to break the message , Break on the button class
Click on “check” Rear disconnect , But the knowledge of message breakpoints is not very good , I can't trace back to the address I jumped back to after message processing .

So I changed my mind
Yes EditText , So I thought of the method I used before
analysis :

  1. The contents of the edit box are stored in memory
  2. Click on check After accessing the memory, fetch the value

 Insert picture description here
 Insert picture description here
Access to memory through value taking operation , Location of positioning function
 Insert picture description here
Sure enough, I succeeded in catching up with the function , At the same time, I saw win32API GetDialogTextA() function , Here, I also expand my knowledge points , In the future, you can use API The breakpoint GetDialogTextA

 Insert picture description here
First of all, I set a breakpoint on the function header , It is found that this function is probably a callback function of window messages , It's a switch, Classify messages .

 Insert picture description here
call .00401000 Before this function push Two parameters
The pressing parameters are :

  1. Name
  2. KeyCode
    With cmp eax,0x1, then jnz switch Of default Branch , No more execution
    So we can guess that if the verification is successful, then eax Should be stored in 0x1

At this time, I began to play smart , Then I thought it was just a pop-up message box , stay jnz When the time is right ZFLAG Just change it , Or the eax Change it to 0x1, Later, I looked at the topic carefully , Let me submit a Code

0x3 obtain Code analysis

First of all, we need to analyze the principle of the registration machine , We enter a registration code , The program generates a correct registration code , Compare the two , So as to judge whether it is correct .

So get Code There are ways 2 Kind of :

  1. Parse generation Code The algorithm of
  2. Find the generated through dynamic debugging Code Use directly

0x4 Analysis compilation

00401000  /$  53            push ebx                                 ;   become an independent school .00406A30
00401001  |.  8B5C24 0C     mov ebx,dword ptr ss:[esp+0xC]           ;   become an independent school .0040125C
00401005  |.  55            push ebp
00401006  |.  56            push esi                                 ;   become an independent school .00406930
00401007  |.  8B7424 10     mov esi,dword ptr ss:[esp+0x10]          ;   become an independent school .00406930
0040100B  |.  8A0B          mov cl,byte ptr ds:[ebx]
0040100D  |.  33ED          xor ebp,ebp
0040100F  |.  57            push edi
00401010  |.  8A06          mov al,byte ptr ds:[esi]
00401012  |.  3AC1          cmp al,cl
00401014  |.  0F85 69010000 jnz  become an independent school .00401183
 Push the  0x1
 assignment  ebx  by  "keycode"
 Push the  ebp  I don't know what it is 
 Push the  esi  in  getDialogTextA() Function address 
 assignment  esi  by   account number 
 assignment  cl  by  [ebx] One byte of   'cl  by keycode First character '
 Exclusive or  ebp,ebp
 Push the  edi 0x0
 assignment  al  by  [esi] The first byte of  'al  Is the first character of the user name '
 Compare  al  and  cl Whether it is equal or not 
 If equal, continue , Otherwise jump to  00401183 ' End function '
//----------------------------------------------- Here we analyze keycode The first character is C
0040101A  |.  8BFE          mov edi,esi                              ;   become an independent school .00406930
0040101C  |.  83C9 FF       or ecx,-0x1
0040101F  |.  33C0          xor eax,eax
00401021  |.  F2:AE         repne scas byte ptr es:[edi]
00401023  |.  F7D1          not ecx                                  ;  user32.75860043
00401025  |.  49            dec ecx                                  ;  user32.75860043
00401026  |.  83F9 05       cmp ecx,0x5
00401029  |. /0F82 54010000 jb  become an independent school .00401183

Knowledge point :
repne scas Used to traverse strings in assembly
ecx adopt or ecx,-0x1 Initialize to FFFFFFFF
stay edi Store string in , stay AL Store characters in
Each cycle ecx - 1
not ecx Take the opposite
dec ecx Minus one # Because the real string length is to subtract one after the string traverses to the last stop character

 assignment  edi  by  esi ' user name '
 Get the length of the user name to  ecx
 Compare ecx and 0x5
//----------------------------------------------- Here we can analyze that the length of the user name is at least 5
0040102F  |.  807B 01 2D    cmp byte ptr ds:[ebx+0x1],0x2D
00401033  |.  0F85 4A010000 jnz  become an independent school .00401183
//----------------------------------------------- Judge KeyCode Whether the second character is  0x2D '-'

From the analysis here, we can know the following points :

  1. CODE The prefix for ‘C-’
  2. The user name must be at least 5
00401039  |.  8BFE          mov edi,esi                              ;   become an independent school .00406930
0040103B  |.  83C9 FF       or ecx,-0x1
0040103E  |.  33C0          xor eax,eax
00401040  |.  33D2          xor edx,edx
00401042  |.  F2:AE         repne scas byte ptr es:[edi]
00401044  |.  F7D1          not ecx
00401046  |.  49            dec ecx

This code looks familiar , There is , Just take it out EDI Medium string length

00401049  |> /0FBE0C32      /movsx ecx,byte ptr ds:[edx+esi]
0040104D  |. |03E9          |add ebp,ecx
0040104F  |. |8BFE          |mov edi,esi                             ;   become an independent school .00406930
00401051  |. |83C9 FF       |or ecx,-0x1
00401054  |. |33C0          |xor eax,eax
00401056  |. |42            |inc edx
00401057  |. |F2:AE         |repne scas byte ptr es:[edi]
00401059  |. |F7D1          |not ecx
0040105B  |. |49            |dec ecx
0040105C  |. |3BD1          |cmp edx,ecx
0040105E  |.^\72 E9         \jb short  become an independent school .00401049

add ebp,0x6064

 Insert picture description here
It can be seen here that it is a cycle , The pop-up condition is edx == ecx,ecx The length of the user name is stored in
The operation of the loop is to traverse each character of the string , Character ASCII Value added to ebp in
The first sentence is to take out edx + esi One character of the address ,edx The initial value is 0, With the cycle inc edx Increasing
After jumping out of the loop ebp Another constant is added

00401066  |.  55            push ebp
00401067  |.  68 34604000   push  become an independent school .00406034                       ;  ASCII "%lu"
0040106C  |.  68 306B4000   push  become an independent school .00406B30                       ;  ASCII "49796"
00401071  |.  E8 B6030000   call  become an independent school .0040142C

The more you look at it, the more something goes wrong , The first question is not so difficult ??
Then I thought about going back , See if you can find a good one CODE.
Sure enough , Ceaseless F8 You can get

0040118E  |.  BF 446B4000   mov edi, become an independent school .00406B44                    ;  ASCII "C-B25120-49796"

So although I have this right Code, If the topic is a little difficult , He wants to randomly generate the user's registration code , So the solution is 2 Kind of :

  1. HOOK Generate Code Function of , Get the right Code
  2. Analyze the encryption algorithm

0x5 Analyze the encryption algorithm to realize the registration machine

This is actually beyond the outline , The problem solving lies in 0X4 It's over . If you are interested, please continue to look down .

How to judge the correct algorithm flow ? We already have the right Code, So follow the right Code Should be able to run out of the right process .

00401076  |.  8A16          mov dl,byte ptr ds:[esi]
00401078  |.  8BFE          mov edi,esi                              ;   become an independent school .00406930
0040107A  |.  83C9 FF       or ecx,-0x1
0040107D  |.  33C0          xor eax,eax
0040107F  |.  8815 446B4000 mov byte ptr ds:[0x406B44],dl
00401085  |.  C605 456B4000>mov byte ptr ds:[0x406B45],0x2D
0040108C  |.  F2:AE         repne scas byte ptr es:[edi]
0040108E  |.  F7D1          not ecx
00401090  |.  49            dec ecx
00401091  |.  0FBE4431 FF   movsx eax,byte ptr ds:[ecx+esi-0x1]
00401096  |.  50            push eax
00401097  |.  E8 C4020000   call  become an independent school .00401360

This compilation , First, take out the length of the user name
then movsx eax,byte ptr ds:[ecx+esi-0x1], Take out the last character
push eax Put this character on the stack , Perform the following functions , But the following function has no effect on the stack and registers of the program after execution , So this function is negligible .

0040109C  |.  A2 466B4000   mov byte ptr ds:[0x406B46],al
004010A1  |.  BF 306B4000   mov edi, become an independent school .00406B30                    ;  ASCII "25120"
004010A6  |.  83C9 FF       or ecx,-0x1
004010A9  |.  33C0          xor eax,eax
004010AB  |.  F2:AE         repne scas byte ptr es:[edi]
004010AD  |.  F7D1          not ecx
004010AF  |.  2BF9          sub edi,ecx
004010B1  |.  81C5 64600000 add ebp,0x6064

This code is familiar , Then we add 0x6064

 Insert picture description here
I see it here C-B, Then look up at the assignment statement
 Insert picture description here
guess 0x406B44 Is the first address of the string array

Through the later debugging, it is found that key The format is C-{ The last character of the user }{ Come by calculation }-{ Come by calculation }
The address is 00406B30, This data is important
So make a break for him , When does the locator write to this memory

In this way, I located inside the algorithm , Then return to the upper function , Located in the real encryption function

 Insert picture description here
But it is found that this value already exists in the stack , Explain that before executing this function , It has been encrypted .
So trace back to the previously called function

00401F2A  |> /8B45 F0       |/mov eax,[local.4]
00401F2D  |. |FF4D F0       ||dec [local.4]
00401F30  |. |85C0          ||test eax,eax
00401F32  |. |7F 06         ||jg short  become an independent school .00401F3A
00401F34  |. |8BC6          ||mov eax,esi
00401F36  |. |0BC7          ||or eax,edi
00401F38  |. |74 3B         ||je short  become an independent school .00401F75
00401F3A  |> |8B45 F4       ||mov eax,[local.3]
00401F3D  |. |99            ||cdq
00401F3E  |. |52            ||push edx
00401F3F  |. |50            ||push eax
00401F40  |. |57            ||push edi
00401F41  |. |56            ||push esi
00401F42  |. |8945 C0       ||mov [local.16],eax
00401F45  |. |8955 C4       ||mov [local.15],edx
00401F48  |. |E8 03150000   ||call  become an independent school .00403450
00401F4D  |. |FF75 C4       ||push [local.15]
00401F50  |. |8BD8          ||mov ebx,eax
00401F52  |. |83C3 30       ||add ebx,0x30
00401F55  |. |FF75 C0       ||push [local.16]
00401F58  |. |57            ||push edi
00401F59  |. |56            ||push esi
00401F5A  |. |E8 81140000   ||call  become an independent school .004033E0
00401F5F  |. |83FB 39       ||cmp ebx,0x39
00401F62  |. |8BF0          ||mov esi,eax
00401F64  |. |8BFA          ||mov edi,edx
00401F66  |. |7E 03         ||jle short  become an independent school .00401F6B
00401F68  |. |035D D4       ||add ebx,[local.11]
00401F6B  |> |8B45 F8       ||mov eax,[local.2]
00401F6E  |. |FF4D F8       ||dec [local.2]
00401F71  |. |8818          ||mov byte ptr ds:[eax],bl
00401F73  |.^\EB B5         |\jmp short  become an independent school .00401F2A
00401F75  |>  8D45 B7       |lea eax,dword ptr ss:[ebp-0x49]
00401F78  |.  2B45 F8       |sub eax,[local.2]
00401F7B  |.  FF45 F8       |inc [local.2]

Here is the encryption function we want , The first CALL For the key CALL
 Insert picture description here
After repeated analysis, it is found that , The previous compilation has no effect , take esp + 0x8 Location is important , And then through div ecx, There are further discoveries , Find out ECX The value of is constant , From the outer function, we can see ,0XA It's a constant ,div ecx, Put the divisor in EAX in , After treatment, put it in EAX in , The remainder is placed in EDX in , Then go to the next cycle , This quotient is also regarded as the divisible number , Then I also found that the remainder is the reverse output of our first encryption parameter .

So the problem goes back to tracing this EAX Initial value 0x6261 How did it come to ?

I have analyzed one before ebp += User name character ASCII And then add one 0x6064
In order to verify , Me too. eax Trace the source of , The memory access breakpoint , It also happens to return to the position of the previous analysis .
 Insert picture description here
And then just use c++ Write a demo Test the following ideas
 Insert picture description here
Here is 6220 Because the user name I used in the test is the same as that in OD It's not the same in , But if it's the same This value is equal .
So my guess is correct .


Here we find 25120 02152 It's the reverse , I think about it … % 0xA It's a process from hexadecimal to decimal ? So there is no need to recalculate .

The first parameter comes out , The second parameter is not far away , Write breakpoints through the same memory , Trace the key CALL, The discovery finally came to the encryption algorithm we analyzed , It's just eax The initial value is not 0x6220 了 , It's another number , I thought there was another one before ebp+0x6064 Where you live ?
 Insert picture description here
Sure enough, add one 6064 It's ok , Then there is the matter of converting to decimal !

If it is reproduced according to the original algorithm , That should be
 Insert picture description here

But in fact, it is not so complicated , Last code

#include<iostream>
#include<string>
using namespace std;
int main(){
	string name;
	cout<<" enter one user name :";
	cin>>name;
	int strLen =  name.size();
	int ebp,code1,code2;
	code1 = code2 = 0;
	ebp = 0x0;
	for(int i=0;i < strLen;i++){
		ebp += int(name[i]);
	}
	ebp += 0x6064;
	code1 = ebp;
	code2 =code1 +  0x6064;

	cout<<"keys:"<<"C-"<<name[strLen-1]<<code1<<"-"<<code2<<endl;
	return 0;
} 

 Insert picture description here

0x6

Please indicate the source of forwarding , Interested in learning together ~

原网站

版权声明
本文为[TiggerRun]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/187/202207060928240240.html