WEBVTT

1
00:01.480 --> 00:03.430
Hello and welcome back.

2
00:03.580 --> 00:14.500
In the previous lesson, we saw that we can use a method to bypass the UPX Packer by allowing the packed

3
00:14.500 --> 00:20.350
program to first run and then launch our Python script to patch the memory

4
00:20.530 --> 00:25.630
while it is running. Now, in this second, uh,

5
00:26.800 --> 00:27.760
uh, like in this lesson,

6
00:27.760 --> 00:30.610
now we are going to try something different.

7
00:31.000 --> 00:41.770
This time we will use a Python program to run the program itself and then automatically patch the memory.

8
00:42.400 --> 00:44.020
So it's slightly different.

9
00:45.120 --> 00:47.820
So this type of program is called a loader.

10
00:48.360 --> 00:54.390
The loader will launch the program for you and then search for the area where you want to patch, and

11
00:54.390 --> 00:55.590
then apply the patch.

12
00:56.670 --> 01:06.180
So for this video lesson, I have chosen my own Crackme, Crackme 11, which you can actually find from here,

13
01:06.630 --> 01:09.930
or you can download from the resource section for this lecture.

14
01:10.920 --> 01:15.570
So this was written originally to unpack and to create a loader.

15
01:15.900 --> 01:22.230
But for this lesson we are just going to create a loader because I want to show you how Python can actually

16
01:22.230 --> 01:24.600
be used for that purpose.

17
01:25.440 --> 01:32.670
Now the first step before we can use the loader is we have to identify the area where we want to

18
01:32.670 --> 01:33.240
patch.

19
01:33.660 --> 01:37.110
So we have to analyze it first using x64dbg.

20
01:38.490 --> 01:43.980
Before that, we run the program and we see it asks for a serial key.

21
01:44.610 --> 01:51.450
If we enter any serial key, you click on the button "Check" and it gives a message "Sorry, wrong key."

22
01:51.870 --> 01:54.300
So let's just click OK to dismiss it.

23
01:55.470 --> 01:58.500
Now this program, if you scan it with DIE,

24
01:59.990 --> 02:02.420
you will find that it is a 32-bit program,

25
02:02.840 --> 02:07.460
PE32, and it is also packed with UPX Packer.

26
02:08.810 --> 02:09.800
So

27
02:11.220 --> 02:15.120
now let's, uh, open it with, uh, x32dbg.

28
02:17.520 --> 02:18.990
And run the program.

29
02:20.950 --> 02:24.340
Instead of doing a string search, we are going to try something different.

30
02:24.940 --> 02:26.920
We are going to use the call stack method.

31
02:26.920 --> 02:34.180
So the call stack is a place where it lists all the functions that have been called since the program

32
02:34.180 --> 02:34.870
started.

33
02:35.500 --> 02:39.160
The earliest program, the earliest call, is listed at the bottom.

34
02:39.160 --> 02:43.450
The most recent calls are at the top, so that's why it's called a call stack.

35
02:44.780 --> 02:46.280
So let's run it now.

36
02:48.520 --> 02:53.860
So now, since it's running, the program has unpacked itself into memory.

37
02:54.770 --> 02:57.920
So we can enter any wrong serial key.

38
02:58.040 --> 02:59.030
Click "Check."

39
03:00.830 --> 03:01.430
It says "Wrong key."

40
03:01.430 --> 03:01.730
OK.

41
03:02.470 --> 03:04.150
Now we pause the program.

42
03:04.750 --> 03:07.210
Pause the debugger by clicking the pause button.

43
03:07.210 --> 03:10.960
Click on this button and you see the state is now paused.

44
03:11.410 --> 03:12.760
Now we go to the call stack.

45
03:14.120 --> 03:17.450
We look for the user module,

46
03:17.450 --> 03:20.390
the last user, user, user function

47
03:21.000 --> 03:21.930
that was called.

48
03:22.170 --> 03:23.940
These are all system calls.

49
03:24.450 --> 03:26.160
From here onwards, you will see user, user.

50
03:26.160 --> 03:26.730
User.

51
03:27.340 --> 03:30.400
Another characteristic is you can look at the address.

52
03:30.700 --> 03:35.680
If it's a high address like this, seven, seven, and so on, that means it's a system,

53
03:35.680 --> 03:36.820
system call.

54
03:37.390 --> 03:42.040
If it's a low address like, for, like this, then you know it's a user module.

55
03:43.160 --> 03:45.020
Also you can confirm from memory map.

56
03:45.290 --> 03:52.880
You can see the user module is here at this address range, starting with 004 onwards.

57
03:54.490 --> 03:55.360
So let's go back.

58
03:55.360 --> 03:55.630
Now

59
03:55.630 --> 03:59.110
you can see, look for the 004 here.

60
03:59.530 --> 04:00.910
This one is a good candidate.

61
04:02.010 --> 04:02.940
So,

62
04:02.940 --> 04:07.140
so this is a list of all the functions that have been called up to now.

63
04:07.500 --> 04:15.930
So in order to know which function showed the bad message, the bad message, I remind you, is this one.

64
04:16.260 --> 04:18.570
Which function is responsible for showing this?

65
04:19.230 --> 04:21.300
We will trace the call stack.

66
04:21.990 --> 04:30.540
So since this function is, since this, uh, bad message is the latest event, that means the latest

67
04:30.540 --> 04:32.160
call will be at the top.

68
04:33.130 --> 04:37.540
The latest calls which are responsible for that event will be at the top.

69
04:37.540 --> 04:40.900
That's why we are looking, searching from top down rather than bottom up.

70
04:41.680 --> 04:47.530
So we find that 004 is a good candidate to look into.

71
04:47.530 --> 04:49.900
So this is under the column "To."

72
04:50.810 --> 04:52.100
So we right-click on this.

73
04:52.100 --> 04:54.230
Sometimes it can be under column "From," depends.

74
04:54.230 --> 04:57.230
For example, if you're tracing, this will be under column "From."

75
04:57.230 --> 04:59.090
But we want the most recent call,

76
04:59.090 --> 05:01.070
so we trace this one first.

77
05:01.070 --> 05:03.650
If it's wrong, we can always go down and down and down.

78
05:04.220 --> 05:10.460
So now we look at this, right-click "Follow To," because this is under the column "To."

79
05:10.490 --> 05:12.080
So we select "Follow To."

80
05:12.170 --> 05:15.350
If it was under column "From," we select "Follow From."

81
05:17.530 --> 05:22.390
So now you see, this is the place that call was made.

82
05:23.680 --> 05:24.280
This call.

83
05:25.120 --> 05:28.180
So we look up, you can see that there is a,

84
05:29.100 --> 05:29.610
the string

85
05:29.610 --> 05:29.910
"Sorry,

86
05:29.910 --> 05:30.510
wrong key."

87
05:31.440 --> 05:35.010
This is a text and this is the caption for the text box.

88
05:35.960 --> 05:37.730
This is the text and the caption.

89
05:38.630 --> 05:44.060
And so you have two, two, two types of messages which can be shown,

90
05:44.180 --> 05:46.850
and here is the JE, "Jump Equal."

91
05:47.630 --> 05:49.700
So if you put a breakpoint here,

92
05:50.690 --> 05:51.050
right,

93
05:51.050 --> 05:52.970
you can just double-click here to breakpoint.

94
05:53.950 --> 05:55.120
And if you now

95
05:56.610 --> 05:59.280
go back to our program, click OK.

96
06:02.980 --> 06:07.360
OK, we have to run the debugger because we paused it just now, so just run the debugger.

97
06:08.800 --> 06:10.780
And now we go back to our program.

98
06:10.960 --> 06:11.650
OK.

99
06:13.230 --> 06:15.300
And now we click "Check" again.

100
06:15.720 --> 06:16.950
It will hit our breakpoint.

101
06:17.400 --> 06:22.800
And from the breakpoint you will see that the grayed-out line shows that it is not going to jump.

102
06:23.280 --> 06:24.510
It's also confirmed here.

103
06:24.510 --> 06:25.590
Jump is not taken.

104
06:26.130 --> 06:27.780
So it is going to go straight.

105
06:28.260 --> 06:29.790
So we can trace it.

106
06:30.180 --> 06:33.480
Trace coverage with "Step Over."

107
06:33.990 --> 06:35.100
You see it's going straight.

108
06:35.820 --> 06:37.440
It's loading the bad message.

109
06:38.070 --> 06:41.760
And then this is a call that will show the bad message.

110
06:42.360 --> 06:45.750
We step over it and then the bad message is shown.

111
06:45.780 --> 06:46.080
"Sorry,

112
06:46.080 --> 06:46.650
wrong key."

113
06:47.830 --> 06:48.070
OK?

114
06:48.070 --> 06:48.610
OK.

115
06:49.870 --> 06:55.510
So now we know that if we want, if that were the correct message, or we have to reverse the JE jump

116
06:55.810 --> 06:56.080
label.

117
06:56.080 --> 06:57.100
So let's try that again.

118
06:57.460 --> 06:58.330
Now we run.

119
07:00.380 --> 07:01.010
To check.

120
07:02.060 --> 07:03.350
It hits our breakpoint.

121
07:03.770 --> 07:08.120
This time we want to reverse this jump, so we need to patch this.

122
07:08.120 --> 07:12.110
Yes, the original opcode is 74 22.

123
07:12.140 --> 07:14.270
We're going to patch it with JMP.

124
07:14.900 --> 07:17.600
So before we patch it, we just copy this,

125
07:17.600 --> 07:19.010
all these bytes here.

126
07:23.590 --> 07:29.320
Binary copy and open Notepad and paste it into Notepad.

127
07:29.410 --> 07:33.490
So this is the array of bytes that we want to

128
07:36.160 --> 07:37.360
you want to search for.

129
07:39.220 --> 07:42.970
Now, the longer the bytes, the more unique it will be.

130
07:43.090 --> 07:49.720
If you are afraid that this pattern will be found in other parts of this module, then just increase

131
07:49.720 --> 07:51.880
the bytes that you want to search for.

132
07:51.880 --> 07:55.720
For example, like this, binary copy.

133
07:58.080 --> 07:58.950
It's up to you.

134
08:00.120 --> 08:02.070
You can search for a longer pattern like this.

135
08:02.070 --> 08:03.360
Then it will be more unique.

136
08:04.150 --> 08:06.370
So the longer it is, the more unique it gets.

137
08:07.000 --> 08:13.270
We want it quite unique so that there will not be two locations in the executable that have the end, in an...

138
08:13.270 --> 08:15.280
Otherwise you'll be patching twice.

139
08:16.530 --> 08:21.570
I have done this before, and I found that this one is good enough, so we don't need to go for such

140
08:21.570 --> 08:23.460
a long array of bytes.

141
08:24.240 --> 08:25.470
So we use this.

142
08:26.040 --> 08:31.350
So we want to patch this one to become a jump,

143
08:31.380 --> 08:32.400
unconditional jump.

144
08:32.400 --> 08:33.810
That means we want it to jump here.

145
08:34.230 --> 08:39.150
So we assemble a, assemble an assembler instruction here.

146
08:39.150 --> 08:40.050
Press spacebar.

147
08:40.680 --> 08:42.960
And then we assemble a JMP.

148
08:44.590 --> 08:46.060
Now make sure this is checked.

149
08:46.060 --> 08:48.010
And you see instruction is same size.

150
08:48.580 --> 08:50.170
So when you click OK,

151
08:50.960 --> 08:51.500
close this,

152
08:51.740 --> 08:53.810
you see that only one byte needs to be changed.

153
08:53.840 --> 08:54.230
-.

154
08:55.310 --> 08:59.420
You compare it here, that means you only need to change this byte to become -.

155
08:59.540 --> 09:01.070
The rest remains unchanged.

156
09:01.640 --> 09:05.600
So this is the array of bytes and then go down.

157
09:05.840 --> 09:06.770
This is -.

158
09:07.910 --> 09:15.050
So we are identifying the array of bytes that we are going to scan for and the bytes that we want to

159
09:15.050 --> 09:15.740
replace,

160
09:16.550 --> 09:17.630
to replace this.

161
09:17.840 --> 09:22.850
So we'll just pause here and I'll come back and see you in the next lesson.

162
09:22.880 --> 09:23.990
Don't close everything.

163
09:23.990 --> 09:25.130
We'll see you in the next lesson.

164
09:25.460 --> 09:26.600
Thank you for watching.