首页
社区
课程
招聘
4
[原创]看雪CTF.TSRC 2018 团队赛第六题追凶者也WP
发表于: 2018-12-13 11:29 4357

[原创]看雪CTF.TSRC 2018 团队赛第六题追凶者也WP

2018-12-13 11:29
4357

发现在Exports中有tlscallback,好了,我们首先看看在tls中做了什么?

     函数 401A10 为真正的check函数,其调用 sub_401290函数,如果 sub_401290函数返回1,则起再次计算输入sn的hash值,并判断此hash值是否等于0x5634D252,如果相等,则将全局字串改为; "try again!"改为success'" ,"fail"改为 "ok"。







    将可执行文件拖入Ida分析,可以看到WinMain()入口函数如下:
1
2
3
4
5
6
7
8
9
int __stdcall WinMain()
{
  sub_401280();
  return 0;
}
void sub_401280()
{
  ;
}

1
2
3
4
5
6
7
8
9
int __stdcall WinMain()
{
  sub_401280();
  return 0;
}
void sub_401280()
{
  ;
}

程序sub_401280()是一个空函数,看来有其他奥妙了。

发现在Exports中有tlscallback,好了,我们首先看看在tls中做了什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
HANDLE __stdcall TlsCallback_0(int a1, int a2, int a3)
{
  HANDLE result; // eax
  int Parameter; // [esp+Ch] [ebp-8h]
  int v5; // [esp+10h] [ebp-4h]
 
  result = (HANDLE)0xCCCCCCCC;
  Parameter = 0xCCCCCCCC;
  v5 = 0xCCCCCCCC;
  if ( a2 == 1 )
  {
    sub_401D50();
    InitializeCriticalSection(&CriticalSection);
    sub_401C10();
    result = CreateThread(0, 0, StartAddress, &Parameter, 0, 0);
  }
  return result;
}

  1. 我们首先分析sub_401D50()函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int sub_401D50()
{
  signed int i; // [esp+0h] [ebp-18h]
  int v2[3]; // [esp+Ch] [ebp-Ch]
 
  v2[1] = 0xCCCCCCCC;
  v2[2] = 0xCCCCCCCC;
  v2[0] = 0xE9;
  *(int *)((char *)v2 + 1) = (char *)off_414014 - (char *)((_BYTE *)off_414018 + 4) - 5;    //组织jmp指令
  sub_4019B0(off_414018);
  for ( i = 0; i < 5; ++i )
    *((_BYTE *)off_414018 + i + 4) = *((_BYTE *)v2 + i);                                    //插入jmp指令                       
  return sub_4019E0(off_414018);
}
1
2
.data:00414014 off_414014      dd offset sub_401220    ; DATA XREF: sub_401D50+45↑r
.data:00414018 off_414018      dd offset sub_401280    ; DATA XREF: sub_401D50+3D↑r

可以看到:
全局变量off_414018存储着sub_401280()函数地址,而该函数就是 WinMain()中那个空函数地址。
全局变量off_414018存储着 sub_401220()
这里在 sub_401280()中插入了 sub_401220()函数调用。修改前后对比如下图:

sub_11220()函数如下:
1
2
3
4
5
6
7
8
void __noreturn sub_401220()
{
  HINSTANCE hInstance; // ST18_4
 
  hInstance = GetModuleHandleW(0);
  DialogBoxParamW(hInstance, (LPCWSTR)0x65, 0, DialogFunc, 0);
  exit(0);
}

我们暂时先放下TLS分析,看看DialogFunc()函数,在该函数里主要是调用了sub_401040()这个函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
int __cdecl sub_401040(HWND hDlg)
{
  void *v1; // ST08_4
  signed int i; // [esp+Ch] [ebp-24h]
  signed int v4; // [esp+10h] [ebp-20h]
  CHAR String; // [esp+18h] [ebp-18h]
  int v6; // [esp+19h] [ebp-17h]
  int v7; // [esp+1Dh] [ebp-13h]
  int v8; // [esp+21h] [ebp-Fh]
  int v9; // [esp+25h] [ebp-Bh]
  __int16 v10; // [esp+29h] [ebp-7h]
  char v11; // [esp+2Bh] [ebp-5h]
 
  strcpy(Text, "try again!");                   // //看到了,我们验证失败时候的字串
  strcpy(Caption, "fail");
  String = 0;
  v6 = 0;
  v7 = 0;
  v8 = 0;
  v9 = 0;
  v10 = 0;
  v11 = 0;
  GetDlgItemTextA(hDlg, 1001, &String, 20);
  v4 = 0;
  for ( i = 0; i < 20; ++i )
    v4 += *(&String + i);
  if ( v4 > 0 && v4 < 4132 )
  {
    v1 = malloc(v4);
    sub_401020();
    j___free_base(v1);
  }
  return MessageBoxA(0, Text, Caption, 0);
}
然而sub_401020()函数又是一个空函数,带着这个问题,我们继续分析TLS后面的内容。

  2.分析sub_401C10()函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int sub_401C10()
{
  void *v0; // edx
  signed int j; // [esp+0h] [ebp-Ch]
  signed int i; // [esp+8h] [ebp-4h]
 
  sub_4018D0();
  lpAddress = v0;
  sub_4019B0(v0);
  for ( i = 0; i < 5; ++i )
    byte_4147DC[i] = *((_BYTE *)lpAddress + i + 32);
  *(_DWORD *)&byte_414028[1] = (char *)sub_401A10 - (char *)((_BYTE *)lpAddress + 32) - 5;
  for ( j = 0; j < 5; ++j )
    *((_BYTE *)lpAddress + j + 32) = byte_414028[j];
  return sub_4019E0(lpAddress);
}
这个函数看着和上一个函数很像,关键是v0(edx)指向的是什么地址呢?v0中的值看上去应该是  sub_4018D0()初始化的。先来看看这个函数。
分析这个函数之前我们先来温习点功课:FS段寄存器,TEB结构,PEB结构
      1)FS段寄存器指向当前的TEB结构,在TEB编译0x30处是PEB指针,通过这个指针即可获得PED的地址。
      2) TEB和PEB的结构如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
typedef struct _NT_TIB
{                                           // Size: 01C
    struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList; // 000
    PVOID StackBase;                        // 004
    PVOID StackLimit;                       // 008
    PVOID SubSystemTib;                     // 00C
    union                                   // 010
    {
        PVOID FiberData;
        ULONG Version;
    };
    PVOID ArbitraryUserPointer;             // 014
    struct _NT_TIB *Self;                   // 018
} NT_TIB, *PNT_TIB;
  
typedef struct _TEB 
{                                           // Size:  FBC
    NT_TIB Tib;                             // 000
    PVOID EnvironmentPointer;               // 01C
    CLIENT_ID Cid;                          // 020
    PVOID ActiveRpcHandle;                  // 028
    PVOID ThreadLocalStoragePointer;        // 02C
    struct _PEB *ProcessEnvironmentBlock;   // 030
    ULONG LastErrorValue;                   // 034
    ULONG CountOfOwnedCriticalSections;     // 038
    PVOID CsrClientThread;                  // 03C
    struct _W32THREAD* Win32ThreadInfo;     // 040
    ULONG User32Reserved[0x1A];             // 044
    ULONG UserReserved[5];                  // 0AC
    PVOID WOW32Reserved;                    // 0C0
    LCID CurrentLocale;                     // 0C4
    ULONG FpSoftwareStatusRegister;         // 0C8
    PVOID SystemReserved1[0x36];            // 0CC
    LONG ExceptionCode;                     // 1A4
    struct _ACTIVATION_CONTEXT_STACK *ActivationContextStackPointer; // 1A8
    UCHAR SpareBytes1[0x28];                // 1AC    
    GDI_TEB_BATCH GdiTebBatch;              // 1D4    
    CLIENT_ID RealClientId;                 // 6B4    
    PVOID GdiCachedProcessHandle;           // 6BC    
    ULONG GdiClientPID;                     // 6C0
    ULONG GdiClientTID;                     // 6C4    
    PVOID GdiThreadLocalInfo;               // 6C8    
    ULONG Win32ClientInfo[62];              // 6CC    
    PVOID glDispatchTable[0xE9];            // 7C4    
    ULONG glReserved1[0x1D];                // B68    
    PVOID glReserved2;                      // BDC    
    PVOID glSectionInfo;                    // BE0    
    PVOID glSection;                        // BE4    
    PVOID glTable;                          // BE8    
    PVOID glCurrentRC;                      // BEC    
    PVOID glContext;                        // BF0    
    NTSTATUS LastStatusValue;               // BF4    
    UNICODE_STRING StaticUnicodeString;     // BF8    
    WCHAR StaticUnicodeBuffer[0x105];       // C00    
    PVOID DeallocationStack;                // E0C    
    PVOID TlsSlots[0x40];                   // E10    
    LIST_ENTRY TlsLinks;                    // F10    
    PVOID Vdm;                              // F18    
    PVOID ReservedForNtRpc;                 // F1C    
    PVOID DbgSsReserved[0x2];               // F20    
    ULONG HardErrorDisabled;                // F28    
    PVOID Instrumentation[14];              // F2C    
    PVOID SubProcessTag;                    // F64    
    PVOID EtwTraceData;                     // F68    
    PVOID WinSockData;                      // F6C    
    ULONG GdiBatchCount;                    // F70    
    BOOLEAN InDbgPrint;                     // F74    
    BOOLEAN FreeStackOnTermination;         // F75    
    BOOLEAN HasFiberData;                   // F76    
    UCHAR IdealProcessor;                   // F77    
    ULONG GuaranteedStackBytes;             // F78    
    PVOID ReservedForPerf;                  // F7C    
    PVOID ReservedForOle;                   // F80    
    ULONG WaitingOnLoaderLock;              // F84    
    ULONG SparePointer1;                    // F88    
    ULONG SoftPatchPtr1;                    // F8C    
    ULONG SoftPatchPtr2;                    // F90    
    PVOID *TlsExpansionSlots;               // F94    
    ULONG ImpersionationLocale;             // F98    
    ULONG IsImpersonating;                  // F9C    
    PVOID NlsCache;                         // FA0    
    PVOID pShimData;                        // FA4    
    ULONG HeapVirualAffinity;               // FA8    
    PVOID CurrentTransactionHandle;         // FAC
    PTEB_ACTIVE_FRAME ActiveFrame;          // FB0    
    PVOID FlsData;                          // FB4    
    UCHAR SafeThunkCall;                    // FB8    
    UCHAR BooleanSpare[3];                  // FB9
} TEB, *PTEB; 
  
typedef struct _LIST_ENTRY
{                                           // Size: 008
    struct _LIST_ENTRY *Flink;              // 000 从前到后
    struct _LIST_ENTRY *Blink;              // 004 从后到前
} LIST_ENTRY, *PLIST_ENTRY;
  
typedef struct _PER_LDR_DATA
{                                           // Size: 0024
    ULONG Length;                           // 000
    BOOLEAN Initialize;                     // 004
    PVOID SsHandle;                         // 008
    LIST_ENTRY InLoadOrderModuleList;       // 00C
    LIST_ENTRY InMemoryOrderModuleList;     // 014
    LIST_ENTRY InInitializationOrderModuleList; // 01C
} PER_LDR_DATA, *PPER_LDR_DATA;
  
typedef struct _UNICODE_STRING 
{                                           // Size: 008
  USHORT  Length;                           // 000 占用的内存字节数,个数*2;
  USHORT  MaximumLength;                    // 002
  PWSTR  Buffer;                            // 004
} UNICODE_STRING ,*PUNICODE_STRING;
  
typedef struct _LDR_DATA_TABLE_ENTRY
{                                           // Size: 050
     LIST_ENTRY InLoadOrderLinks;           // 000 LIST_ENTRY里的Flink和Blink其实是指向LDR_MODULE结构,即LDR_DATA_TABLE_ENTRY
     LIST_ENTRY InMemoryOrderLinks;         // 008 同上
     LIST_ENTRY InInitializationOrderLinks; // 010 同上
     PVOID DllBase;                         // 018
     PVOID EntryPoint;                      // 01C
     ULONG SizeOfImage;                     // 020
     UNICODE_STRING FullDllName;            // 024
     UNICODE_STRING BaseDllName;            // 02C
     ULONG Flags;                           // 034
     WORD LoadCount;                        // 038
     WORD TlsIndex;                         // 03A
     union                                  // 03C
     {
          LIST_ENTRY HashLinks;             // 03C
          struct
          {
               PVOID SectionPointer;        // 03C
               ULONG CheckSum;              // 040
          };
     };
     union
     {
          ULONG TimeDateStamp;              // 044
          PVOID LoadedImports;              // 044
     };
     _ACTIVATION_CONTEXT * EntryPointActivationContext; // 048
     PVOID PatchInformation;                // 04C
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
  
typedef struct _PEB  
{                                           // Size: 1D8   
    UCHAR InheritedAddressSpace;            // 000  
    UCHAR ReadImageFileExecOptions;         // 001  
    UCHAR BeingDebugged;                    // 002   
    UCHAR SpareBool;                        // 003 Allocation size  
    HANDLE Mutant;                          // 004   
    HINSTANCE ImageBaseAddress;             // 008 
    struct _PER_LDR_DATA *Ldr;              // 00C
    strcut _RTL_USER_PPROCESS_PARAMETERS *ProcessParameters; // 010  
    ULONG SubSystemData;                    // 014  
    HANDLE DefaultHeap;                     // 018  
    KSPIN_LOCK FastPebLock;                 // 01C  
    ULONG FastPebLockRoutine;               // 020  
    ULONG FastPebUnlockRoutine;             // 024  
    ULONG EnvironmentUpdateCount;           // 028  
    ULONG KernelCallbackTable;              // 02C  
    LARGE_INTEGER SystemReserved;           // 030  
    struct _PER_FREE_BLOCK *FreeList;       // 038
    ULONG TlsExpansionCounter;              // 03C  
    ULONG TlsBitmap;                        // 040  
    LARGE_INTEGER TlsBitmapBits;            // 044  
    ULONG ReadOnlySharedMemoryBase;         // 04C  
    ULONG ReadOnlySharedMemoryHeap;         // 050  
    ULONG ReadOnlyStaticServerData;         // 054 
    ULONG AnsiCodePageData;                 // 058  
    ULONG OemCodePageData;                  // 05C  
    ULONG UnicodeCaseTableData;             // 060  
    ULONG NumberOfProcessors;               // 064   
    LARGE_INTEGER NtGlobalFlag;             // 068 Address of a local copy  
    LARGE_INTEGER CriticalSectionTimeout;   // 070  
    ULONG HeapSegmentReserve;               // 078  
    ULONG HeapSegmentCommit;                // 07C  
    ULONG HeapDeCommitTotalFreeThreshold;   // 080  
    ULONG HeapDeCommitFreeBlockThreshold;   // 084  
    ULONG NumberOfHeaps;                    // 088  
    ULONG MaximumNumberOfHeaps;             // 08C  
    ULONG ProcessHeaps;                     // 090  
    ULONG GdiSharedHandleTable;             // 094  
    ULONG ProcessStarterHelper;             // 098  
    ULONG GdiDCAttributeList;               // 09C  
    KSPIN_LOCK LoaderLock;                  // 0A0  
    ULONG OSMajorVersion;                   // 0A4  
    ULONG OSMinorVersion;                   // 0A8  
    USHORT OSBuildNumber;                   // 0AC  
    USHORT OSCSDVersion;                    // 0AE  
    ULONG OSPlatformId;                     // 0B0  
    ULONG ImageSubsystem;                   // 0B4  
    ULONG ImageSubsystemMajorVersion;       // 0B8  
    ULONG ImageSubsystemMinorVersion;       // 0BC  
    ULONG ImageProcessAffinityMask;         // 0C0  
    ULONG GdiHandleBuffer[0x22];            // 0C4  
    ULONG PostProcessInitRoutine;           // 14C  
    ULONG TlsExpansionBitmap;               // 150  
    UCHAR TlsExpansionBitmapBits[0x80];     // 154  
    ULONG SessionId;                        // 1D4    
} PEB, *PPEB;
好了有了TEB,PEB数据结构的支撑,我们来分析 sub_4018D0()函数
1
2
3
4
5
6
7
int sub_4018D0()
{
  int v0; // edx
 
  sub_4018F5(0x3BD696F4);
  return sub_401928(v0, 0x925DF53F);
}
0x3BD696F4是目标字串hash值,继续分析 sub_4018F5()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int __stdcall sub_4018F5(int hash)
{
  int hash_1; // ecx
  _DWORD *v2; // esi
  int hash_2; // ST08_4
  int v4; // ST04_4
  int len; // eax
  int result; // eax
  int v7; // edx
 
  hash_1 = hash;
  v2 = *(_DWORD **)(*(_DWORD *)(__readfsdword(0x30u) + 0xC) + 0x1C);// v2 = LIST_ENTRY InInitializationOrderModuleList;
  do
  {
    v2 = (_DWORD *)*v2;
    hash_2 = hash_1;
    v4 = v2[6];                                 // 获取FullDllName;
    len = strlen(v2[6]);                        // 计算字符串长度
    result = getHash(v4, 2 * len);              // 计算hash
    hash_1 = hash_2;
  }
  while ( result != hash_2 );
  v7 = v2[2];                                   // 获得指定dll基址(DllBase)
  return result;
0x30处是PEB的指针  :struct _PEB *ProcessEnvironmentBlock;// 030
PEB+0xc处的指针      :struct _PER_LDR_DATA *Ldr;// 00C
Ldr +0x1c处的指针     :LIST_ENTRY InInitializationOrderModuleList;
目标动态库:C:\Windows\syswow64\USER32.dll 基址存储在edx中
可以看到sub_4018F5(int hash)是根据指定hash获得动态库基址。将DLL基址和目标函数hash传入sub_401928()函数, 继续分析
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
int __stdcall sub_401928(int dllbase, int funcHash)
{
  _DWORD *v2; // esi
  int i; // eax
  int v4; // esi
  int v5; // eax
  int v7; // [esp-8h] [ebp-14h]
  int v8; // [esp+0h] [ebp-Ch]
  int v9; // [esp+4h] [ebp-8h]
  int v10; // [esp+8h] [ebp-4h]
 
  v2 = (_DWORD *)(dllbase + *(_DWORD *)(dllbase + *(_DWORD *)(dllbase + 0x3C) + 0x78));
  v10 = v2[7];
  v9 = v2[8];
  v8 = v2[9];
  for ( i = 0; ; i = v7 + 1 )
  {
    v4 = dllbase + *(_DWORD *)(dllbase + v9 + 4 * i);
    v7 = i;
    v5 = sub_401870(dllbase + *(_DWORD *)(dllbase + v9 + 4 * i));
    if ( getHash(v4, v5) == funcHash )
      break;
  }
  return dllbase + *(_DWORD *)(dllbase + v10 + 4 * *(unsigned __int16 *)(dllbase + v8 + 2 * v7));
}

该函数返回目标函数地址,目标函数为:GetDlgItemTextA()
这样找到了lpAddress指向的地址 GetDlgItemTextA()。我们看一下sub_401c10()函数修改后 GetDlgItemTextA()的情况
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
                    user32_GetDlgItemTextA proc near
user32.dll:76326BCE
user32.dll:76326BCE                arg_0= dword ptr  8
user32.dll:76326BCE                arg_4= dword ptr  0Ch
user32.dll:76326BCE                arg_8= dword ptr  10h
user32.dll:76326BCE                arg_C= dword ptr  14h
user32.dll:76326BCE
user32.dll:76326BCE 8B FF          mov     edi, edi
user32.dll:76326BD0 55             push    ebp
user32.dll:76326BD1 8B EC          mov     ebp, esp
user32.dll:76326BD3 FF 75 0C       push    [ebp+arg_4]
user32.dll:76326BD6 FF 75 08       push    [ebp+arg_0]
user32.dll:76326BD9 E8 7C CB FA FF call    near ptr user32_GetDlgItem
user32.dll:76326BDE 85 C0          test    eax, eax
user32.dll:76326BE0 74 0E          jz      short near ptr loc_76326BEE+2
user32.dll:76326BE2 FF 75 14       push    [ebp+arg_C]
user32.dll:76326BE5 FF 75 10       push    [ebp+arg_8]
user32.dll:76326BE8 50             push    eax
user32.dll:76326BE9 E8 53 94 FA FF call    near ptr user32_GetWindowTextA
user32.dll:76326BEE
user32.dll:76326BEE                loc_76326BEE:                           ; CODE XREF: user32_GetDlgItemTextA+12↑j
user32.dll:76326BEE E9 1D AE CE 89 jmp     sub_11A10
在执行 GetDlgItemTextA()后会jmp 到sub_11A10()执行。我们翻回头在看 DialogFunc ,TLS并没有对sub_401020()做什么,而是在 GetDlgItemTextA()函数尾hook了该函数,转而执行 sub_11A10()。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
int __usercall sub_401A10@<eax>(int a1@<ecx>, int a2@<ebp>, int a3@<esi>)
{
  unsigned int v3; // et0
  int v4; // eax
  _BYTE *v5; // ecx
  unsigned int v7; // [esp-24h] [ebp-24h]
  int v8; // [esp-18h] [ebp-18h]
 
  v8 = a1;
  v3 = __readeflags();
  v7 = v3;
  dword_414800 = a3;
  dword_4147EC = *(_DWORD *)(a2 + 20);
  dword_4147F0 = malloc(dword_4147EC);
  dword_4147F4 = a2 + 16;
  memmove(dword_4147F0, *(const void **)(a2 + 16), dword_4147EC);
  *(_DWORD *)(a2 - 16) = dword_4147F0;
  *(_DWORD *)(a2 - 20) = *(_DWORD *)(a2 - 16) + 1;
  do
    *(_BYTE *)(a2 - 21) = *(_BYTE *)(*(_DWORD *)(a2 - 16))++;
  while ( *(_BYTE *)(a2 - 21) );
  *(_DWORD *)(a2 - 28) = *(_DWORD *)(a2 - 16) - *(_DWORD *)(a2 - 20);
  if ( (unsigned __int8)sub_401290((int)dword_4147F0, *(_DWORD *)(a2 - 28)) )
  {
    v4 = sub_401870((int)dword_4147F0);
    if ( getHash((int)dword_4147F0, v4) == 1446302290 )
    {
      v5 = off_414030;
      *(_WORD *)off_414030 = 0;
      v5[2] = 0;
      for ( *(_WORD *)(a2 - 4) = 0; *(signed __int16 *)(a2 - 4) < 8; ++*(_WORD *)(a2 - 4) )
        *((char *)off_414030 - *(signed __int16 *)(a2 - 4)) = (39 - *(unsigned __int16 *)(a2 - 4)) ^ byte_41401C[7 - *(signed __int16 *)(a2 - 4)];
      *(_WORD *)off_414034 = 0;
      for ( *(_WORD *)(a2 - 8) = 0; *(signed __int16 *)(a2 - 8) < 3; ++*(_WORD *)(a2 - 8) )
        *((char *)off_414034 - *(signed __int16 *)(a2 - 8)) = (34 - *(unsigned __int16 *)(a2 - 8)) ^ byte_414024[2 - *(signed __int16 *)(a2 - 8)];
    }
  }
  j___free_base(dword_4147F0);
  dword_4147F8 = (int (__thiscall *)(_DWORD))((char *)lpAddress + 32);
  sub_4019B0(lpAddress);
  for ( *(_DWORD *)(a2 - 12) = 0; *(_DWORD *)(a2 - 12) < 5; ++*(_DWORD *)(a2 - 12) )
    *((_BYTE *)lpAddress + *(_DWORD *)(a2 - 12) + 32) = byte_4147DC[*(_DWORD *)(a2 - 12)];
  sub_4019E0(lpAddress);
  dword_4147FC = 1;
  __writeeflags(v7);
  return dword_4147F8(v8);
}
到此TLS函数分析完成。

     函数 401A10 为真正的check函数,其调用 sub_401290函数,如果 sub_401290函数返回1,则起再次计算输入sn的hash值,并判断此hash值是否等于0x5634D252,如果相等,则将全局字串改为; "try again!"改为success'" ,"fail"改为 "ok"。

3、判定程序

程序的主要判断逻辑在sub_401290()中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
bool __cdecl sub_401290(char *sn, int len)
{
  byte_4147D0[0] = 4;
  byte_4147D0[1] = 1;
  byte_4147D0[2] = 3;
  byte_4147D0[3] = 7;
  byte_4147D0[4] = 2;
  byte_4147D0[5] = 5;
  byte_4147D0[6] = 8;
  byte_4147D0[7] = 6;
  byte_4147D0[8] = 0;
  return sub_4015B0(sn, len);
}
 
bool __cdecl sub_4015B0(char *sn, int len)
{
  int i; // [esp+0h] [ebp-Ch]
  signed int v4; // [esp+8h] [ebp-4h]
 
  v4 = 0xCCCCCCCC;
  if ( len % 2 )
    return 0;
  for ( i = 0; i < len; i += 2 )
  {
    if ( sn[i] == 'w' )
      v4 = 0;
    if ( sn[i] == 'd' )
      v4 = 1;
    if ( sn[i] == 's' )
      v4 = 2;
    if ( sn[i] == 'a' )
      v4 = 3;
    if ( !(unsigned __int8)sub_401380(v4, sn[i + 1] - 48) )
      return 0;
  }
  return byte_4147D0[0] == 1
      && byte_4147D0[1] == 2
      && byte_4147D0[2] == 3
      && byte_4147D0[3] == 4
      && byte_4147D0[4] == 5
      && byte_4147D0[5] == 6
      && byte_4147D0[6] == 7
      && byte_4147D0[7] == 8
      && !byte_4147D0[8];
}
char __cdecl sub_401380(int a1, int a2)
{
  char result; // al
  signed int i; // [esp+8h] [ebp-8h]
  signed int v4; // [esp+Ch] [ebp-4h]
 
  if ( !a2 )
    return 0;
  v4 = 0;
LABEL_4:
  if ( v4 >= 3 )
    return 0;
  for ( i = 0; ; ++i )
  {
    if ( i >= 3 )
    {
      ++v4;
      goto LABEL_4;
    }
    if ( byte_4147D0[3 * v4 + i] == a2 )
      break;
LABEL_6:
    ;
  }
  switch ( a1 )
  {
    case 0:
      if ( v4 )
      {
        if ( byte_4147D0[3 * (v4 - 1) + i] )
        {
          result = 0;
        }
        else
        {
          byte_4147D0[3 * (v4 - 1) + i] = byte_4147D0[3 * v4 + i];
          byte_4147D0[3 * v4 + i] = 0;
          result = 1;
        }
      }
      else
      {
        result = 0;
      }
      break;
    case 1:
      if ( i == 2 )
      {
        result = 0;
      }
      else if ( byte_4147D1[3 * v4 + i] )
      {
        result = 0;
      }
      else
      {
        byte_4147D1[3 * v4 + i] = byte_4147D0[3 * v4 + i];
        byte_4147D0[3 * v4 + i] = 0;
        result = 1;
      }
      break;
    case 2:
      if ( v4 == 2 )
      {
        result = 0;
      }
      else if ( byte_4147D0[3 * (v4 + 1) + i] )
      {
        result = 0;
      }
      else
      {
        byte_4147D0[3 * (v4 + 1) + i] = byte_4147D0[3 * v4 + i];
        byte_4147D0[3 * v4 + i] = 0;
        result = 1;
      }
      break;
    case 3:
      if ( i )
      {
        if ( byte_4147CF[3 * v4 + i] )
        {
          result = 0;
        }
        else
        {
          byte_4147CF[3 * v4 + i] = byte_4147D0[3 * v4 + i];
          byte_4147D0[3 * v4 + i] = 0;
          result = 1;
        }
      }
      else
      {
        result = 0;
      }
      break;
    default:
      goto LABEL_6;
  }
  return result;
}
     sub_401290函数初始化为char 4147D0[9] = {4,1,3,7,2,5,8,6,0}; 调用sub_4015B0函数根据输入sn对 4147D0[9]内容进行调整(加密)后,如果 char 4147D0[9]值变为 {1,2,3,4,5,6,7,8,0},则成功。算法类似一个简单的华容道,路线如下图:


flag:d6d8s7s4a1w2a5w6















1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
HANDLE __stdcall TlsCallback_0(int a1, int a2, int a3)
{
  HANDLE result; // eax
  int Parameter; // [esp+Ch] [ebp-8h]
  int v5; // [esp+10h] [ebp-4h]
 
  result = (HANDLE)0xCCCCCCCC;
  Parameter = 0xCCCCCCCC;
  v5 = 0xCCCCCCCC;
  if ( a2 == 1 )
  {
    sub_401D50();
    InitializeCriticalSection(&CriticalSection);
    sub_401C10();
    result = CreateThread(0, 0, StartAddress, &Parameter, 0, 0);
  }
  return result;
}

  1. 我们首先分析sub_401D50()函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int sub_401D50()
{
  signed int i; // [esp+0h] [ebp-18h]
  int v2[3]; // [esp+Ch] [ebp-Ch]
 
  v2[1] = 0xCCCCCCCC;
  v2[2] = 0xCCCCCCCC;
  v2[0] = 0xE9;
  *(int *)((char *)v2 + 1) = (char *)off_414014 - (char *)((_BYTE *)off_414018 + 4) - 5;    //组织jmp指令
  sub_4019B0(off_414018);
  for ( i = 0; i < 5; ++i )
    *((_BYTE *)off_414018 + i + 4) = *((_BYTE *)v2 + i);                                    //插入jmp指令                       
  return sub_4019E0(off_414018);
}
1
2
.data:00414014 off_414014      dd offset sub_401220    ; DATA XREF: sub_401D50+45↑r
.data:00414018 off_414018      dd offset sub_401280    ; DATA XREF: sub_401D50+3D↑r

1
2
.data:00414014 off_414014      dd offset sub_401220    ; DATA XREF: sub_401D50+45↑r
.data:00414018 off_414018      dd offset sub_401280    ; DATA XREF: sub_401D50+3D↑r

可以看到:
全局变量off_414018存储着sub_401280()函数地址,而该函数就是 WinMain()中那个空函数地址。
全局变量off_414018存储着 sub_401220()
这里在 sub_401280()中插入了 sub_401220()函数调用。修改前后对比如下图:

sub_11220()函数如下:
1
2
3
4
5
6
7
8
void __noreturn sub_401220()
{
  HINSTANCE hInstance; // ST18_4
 
  hInstance = GetModuleHandleW(0);
  DialogBoxParamW(hInstance, (LPCWSTR)0x65, 0, DialogFunc, 0);
  exit(0);
}
1
2
3
4
5
6
7
8
void __noreturn sub_401220()
{
  HINSTANCE hInstance; // ST18_4
 
  hInstance = GetModuleHandleW(0);
  DialogBoxParamW(hInstance, (LPCWSTR)0x65, 0, DialogFunc, 0);
  exit(0);
}
我们暂时先放下TLS分析,看看DialogFunc()函数,在该函数里主要是调用了sub_401040()这个函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
int __cdecl sub_401040(HWND hDlg)
{
  void *v1; // ST08_4
  signed int i; // [esp+Ch] [ebp-24h]
  signed int v4; // [esp+10h] [ebp-20h]
  CHAR String; // [esp+18h] [ebp-18h]
  int v6; // [esp+19h] [ebp-17h]
  int v7; // [esp+1Dh] [ebp-13h]
  int v8; // [esp+21h] [ebp-Fh]
  int v9; // [esp+25h] [ebp-Bh]
  __int16 v10; // [esp+29h] [ebp-7h]
  char v11; // [esp+2Bh] [ebp-5h]
 
  strcpy(Text, "try again!");                   // //看到了,我们验证失败时候的字串
  strcpy(Caption, "fail");
  String = 0;
  v6 = 0;
  v7 = 0;
  v8 = 0;
  v9 = 0;
  v10 = 0;
  v11 = 0;
  GetDlgItemTextA(hDlg, 1001, &String, 20);
  v4 = 0;
  for ( i = 0; i < 20; ++i )
    v4 += *(&String + i);
  if ( v4 > 0 && v4 < 4132 )
  {
    v1 = malloc(v4);
    sub_401020();
    j___free_base(v1);
  }
  return MessageBoxA(0, Text, Caption, 0);
}
然而sub_401020()函数又是一个空函数,带着这个问题,我们继续分析TLS后面的内容。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
int __cdecl sub_401040(HWND hDlg)
{
  void *v1; // ST08_4
  signed int i; // [esp+Ch] [ebp-24h]
  signed int v4; // [esp+10h] [ebp-20h]
  CHAR String; // [esp+18h] [ebp-18h]
  int v6; // [esp+19h] [ebp-17h]
  int v7; // [esp+1Dh] [ebp-13h]
  int v8; // [esp+21h] [ebp-Fh]
  int v9; // [esp+25h] [ebp-Bh]
  __int16 v10; // [esp+29h] [ebp-7h]
  char v11; // [esp+2Bh] [ebp-5h]
 
  strcpy(Text, "try again!");                   // //看到了,我们验证失败时候的字串
  strcpy(Caption, "fail");
  String = 0;
  v6 = 0;
  v7 = 0;
  v8 = 0;
  v9 = 0;
  v10 = 0;
  v11 = 0;
  GetDlgItemTextA(hDlg, 1001, &String, 20);
  v4 = 0;
  for ( i = 0; i < 20; ++i )
    v4 += *(&String + i);
  if ( v4 > 0 && v4 < 4132 )
  {
    v1 = malloc(v4);
    sub_401020();
    j___free_base(v1);
  }
  return MessageBoxA(0, Text, Caption, 0);
}
然而sub_401020()函数又是一个空函数,带着这个问题,我们继续分析TLS后面的内容。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int sub_401C10()
{
  void *v0; // edx
  signed int j; // [esp+0h] [ebp-Ch]
  signed int i; // [esp+8h] [ebp-4h]
 
  sub_4018D0();
  lpAddress = v0;
  sub_4019B0(v0);
  for ( i = 0; i < 5; ++i )
    byte_4147DC[i] = *((_BYTE *)lpAddress + i + 32);
  *(_DWORD *)&byte_414028[1] = (char *)sub_401A10 - (char *)((_BYTE *)lpAddress + 32) - 5;
  for ( j = 0; j < 5; ++j )
    *((_BYTE *)lpAddress + j + 32) = byte_414028[j];
  return sub_4019E0(lpAddress);
}
这个函数看着和上一个函数很像,关键是v0(edx)指向的是什么地址呢?v0中的值看上去应该是  sub_4018D0()初始化的。先来看看这个函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int sub_401C10()
{
  void *v0; // edx
  signed int j; // [esp+0h] [ebp-Ch]
  signed int i; // [esp+8h] [ebp-4h]
 
  sub_4018D0();
  lpAddress = v0;
  sub_4019B0(v0);
  for ( i = 0; i < 5; ++i )
    byte_4147DC[i] = *((_BYTE *)lpAddress + i + 32);
  *(_DWORD *)&byte_414028[1] = (char *)sub_401A10 - (char *)((_BYTE *)lpAddress + 32) - 5;
  for ( j = 0; j < 5; ++j )
    *((_BYTE *)lpAddress + j + 32) = byte_414028[j];
  return sub_4019E0(lpAddress);
}
这个函数看着和上一个函数很像,关键是v0(edx)指向的是什么地址呢?v0中的值看上去应该是  sub_4018D0()初始化的。先来看看这个函数。
分析这个函数之前我们先来温习点功课:FS段寄存器,TEB结构,PEB结构
      1)FS段寄存器指向当前的TEB结构,在TEB编译0x30处是PEB指针,通过这个指针即可获得PED的地址。
      2) TEB和PEB的结构如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
typedef struct _NT_TIB
{                                           // Size: 01C
    struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList; // 000
    PVOID StackBase;                        // 004
    PVOID StackLimit;                       // 008
    PVOID SubSystemTib;                     // 00C
    union                                   // 010
    {
        PVOID FiberData;
        ULONG Version;
    };
    PVOID ArbitraryUserPointer;             // 014
    struct _NT_TIB *Self;                   // 018
} NT_TIB, *PNT_TIB;
  
typedef struct _TEB 
{                                           // Size:  FBC
    NT_TIB Tib;                             // 000
    PVOID EnvironmentPointer;               // 01C
    CLIENT_ID Cid;                          // 020
    PVOID ActiveRpcHandle;                  // 028
    PVOID ThreadLocalStoragePointer;        // 02C
    struct _PEB *ProcessEnvironmentBlock;   // 030
    ULONG LastErrorValue;                   // 034
    ULONG CountOfOwnedCriticalSections;     // 038
    PVOID CsrClientThread;                  // 03C
    struct _W32THREAD* Win32ThreadInfo;     // 040
    ULONG User32Reserved[0x1A];             // 044
    ULONG UserReserved[5];                  // 0AC
    PVOID WOW32Reserved;                    // 0C0
    LCID CurrentLocale;                     // 0C4
    ULONG FpSoftwareStatusRegister;         // 0C8
    PVOID SystemReserved1[0x36];            // 0CC
    LONG ExceptionCode;                     // 1A4
    struct _ACTIVATION_CONTEXT_STACK *ActivationContextStackPointer; // 1A8
    UCHAR SpareBytes1[0x28];                // 1AC    
    GDI_TEB_BATCH GdiTebBatch;              // 1D4    
    CLIENT_ID RealClientId;                 // 6B4    
    PVOID GdiCachedProcessHandle;           // 6BC    
    ULONG GdiClientPID;                     // 6C0
    ULONG GdiClientTID;                     // 6C4    
    PVOID GdiThreadLocalInfo;               // 6C8    
    ULONG Win32ClientInfo[62];              // 6CC    
    PVOID glDispatchTable[0xE9];            // 7C4    
    ULONG glReserved1[0x1D];                // B68    
    PVOID glReserved2;                      // BDC    
    PVOID glSectionInfo;                    // BE0    
    PVOID glSection;                        // BE4    
    PVOID glTable;                          // BE8    
    PVOID glCurrentRC;                      // BEC    
    PVOID glContext;                        // BF0    
    NTSTATUS LastStatusValue;               // BF4    
    UNICODE_STRING StaticUnicodeString;     // BF8    
    WCHAR StaticUnicodeBuffer[0x105];       // C00    
    PVOID DeallocationStack;                // E0C    
    PVOID TlsSlots[0x40];                   // E10    
    LIST_ENTRY TlsLinks;                    // F10    
    PVOID Vdm;                              // F18    
    PVOID ReservedForNtRpc;                 // F1C    
    PVOID DbgSsReserved[0x2];               // F20    
    ULONG HardErrorDisabled;                // F28    
    PVOID Instrumentation[14];              // F2C    
    PVOID SubProcessTag;                    // F64    
    PVOID EtwTraceData;                     // F68    
    PVOID WinSockData;                      // F6C    
    ULONG GdiBatchCount;                    // F70    
    BOOLEAN InDbgPrint;                     // F74    
    BOOLEAN FreeStackOnTermination;         // F75    
    BOOLEAN HasFiberData;                   // F76    
    UCHAR IdealProcessor;                   // F77    
    ULONG GuaranteedStackBytes;             // F78    
    PVOID ReservedForPerf;                  // F7C    
    PVOID ReservedForOle;                   // F80    
    ULONG WaitingOnLoaderLock;              // F84    
    ULONG SparePointer1;                    // F88    
    ULONG SoftPatchPtr1;                    // F8C    
    ULONG SoftPatchPtr2;                    // F90    
    PVOID *TlsExpansionSlots;               // F94    
    ULONG ImpersionationLocale;             // F98    
    ULONG IsImpersonating;                  // F9C    
    PVOID NlsCache;                         // FA0    
    PVOID pShimData;                        // FA4    
    ULONG HeapVirualAffinity;               // FA8    
    PVOID CurrentTransactionHandle;         // FAC
    PTEB_ACTIVE_FRAME ActiveFrame;          // FB0    
    PVOID FlsData;                          // FB4    
    UCHAR SafeThunkCall;                    // FB8    
    UCHAR BooleanSpare[3];                  // FB9
} TEB, *PTEB; 
  
typedef struct _LIST_ENTRY
{                                           // Size: 008
    struct _LIST_ENTRY *Flink;              // 000 从前到后
    struct _LIST_ENTRY *Blink;              // 004 从后到前
} LIST_ENTRY, *PLIST_ENTRY;
  
typedef struct _PER_LDR_DATA
{                                           // Size: 0024
    ULONG Length;                           // 000
    BOOLEAN Initialize;                     // 004
    PVOID SsHandle;                         // 008
    LIST_ENTRY InLoadOrderModuleList;       // 00C
    LIST_ENTRY InMemoryOrderModuleList;     // 014
    LIST_ENTRY InInitializationOrderModuleList; // 01C
} PER_LDR_DATA, *PPER_LDR_DATA;
  
typedef struct _UNICODE_STRING 
{                                           // Size: 008
  USHORT  Length;                           // 000 占用的内存字节数,个数*2;
  USHORT  MaximumLength;                    // 002
  PWSTR  Buffer;                            // 004
} UNICODE_STRING ,*PUNICODE_STRING;
  
typedef struct _LDR_DATA_TABLE_ENTRY
{                                           // Size: 050
     LIST_ENTRY InLoadOrderLinks;           // 000 LIST_ENTRY里的Flink和Blink其实是指向LDR_MODULE结构,即LDR_DATA_TABLE_ENTRY
     LIST_ENTRY InMemoryOrderLinks;         // 008 同上
     LIST_ENTRY InInitializationOrderLinks; // 010 同上
     PVOID DllBase;                         // 018
     PVOID EntryPoint;                      // 01C
     ULONG SizeOfImage;                     // 020
     UNICODE_STRING FullDllName;            // 024
     UNICODE_STRING BaseDllName;            // 02C
     ULONG Flags;                           // 034
     WORD LoadCount;                        // 038
     WORD TlsIndex;                         // 03A
     union                                  // 03C
     {
          LIST_ENTRY HashLinks;             // 03C
          struct
          {
               PVOID SectionPointer;        // 03C
               ULONG CheckSum;              // 040
          };
     };
     union
     {
          ULONG TimeDateStamp;              // 044
          PVOID LoadedImports;              // 044
     };
     _ACTIVATION_CONTEXT * EntryPointActivationContext; // 048
     PVOID PatchInformation;                // 04C
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
  
typedef struct _PEB  
{                                           // Size: 1D8   
    UCHAR InheritedAddressSpace;            // 000  
    UCHAR ReadImageFileExecOptions;         // 001  
    UCHAR BeingDebugged;                    // 002   
    UCHAR SpareBool;                        // 003 Allocation size  
    HANDLE Mutant;                          // 004   
    HINSTANCE ImageBaseAddress;             // 008 
    struct _PER_LDR_DATA *Ldr;              // 00C
    strcut _RTL_USER_PPROCESS_PARAMETERS *ProcessParameters; // 010  
    ULONG SubSystemData;                    // 014  
    HANDLE DefaultHeap;                     // 018  
    KSPIN_LOCK FastPebLock;                 // 01C  
    ULONG FastPebLockRoutine;               // 020  
    ULONG FastPebUnlockRoutine;             // 024  
    ULONG EnvironmentUpdateCount;           // 028  
    ULONG KernelCallbackTable;              // 02C  
    LARGE_INTEGER SystemReserved;           // 030  
    struct _PER_FREE_BLOCK *FreeList;       // 038
    ULONG TlsExpansionCounter;              // 03C  
    ULONG TlsBitmap;                        // 040  
    LARGE_INTEGER TlsBitmapBits;            // 044  
    ULONG ReadOnlySharedMemoryBase;         // 04C  
    ULONG ReadOnlySharedMemoryHeap;         // 050  
    ULONG ReadOnlyStaticServerData;         // 054 
    ULONG AnsiCodePageData;                 // 058  
    ULONG OemCodePageData;                  // 05C  
    ULONG UnicodeCaseTableData;             // 060  
    ULONG NumberOfProcessors;               // 064   
    LARGE_INTEGER NtGlobalFlag;             // 068 Address of a local copy  
    LARGE_INTEGER CriticalSectionTimeout;   // 070  
    ULONG HeapSegmentReserve;               // 078  
    ULONG HeapSegmentCommit;                // 07C  
    ULONG HeapDeCommitTotalFreeThreshold;   // 080  
    ULONG HeapDeCommitFreeBlockThreshold;   // 084  
    ULONG NumberOfHeaps;                    // 088  
    ULONG MaximumNumberOfHeaps;             // 08C  
    ULONG ProcessHeaps;                     // 090  
    ULONG GdiSharedHandleTable;             // 094  
    ULONG ProcessStarterHelper;             // 098  
    ULONG GdiDCAttributeList;               // 09C  
    KSPIN_LOCK LoaderLock;                  // 0A0  
    ULONG OSMajorVersion;                   // 0A4  
    ULONG OSMinorVersion;                   // 0A8  
    USHORT OSBuildNumber;                   // 0AC  
    USHORT OSCSDVersion;                    // 0AE  
    ULONG OSPlatformId;                     // 0B0  
    ULONG ImageSubsystem;                   // 0B4  
    ULONG ImageSubsystemMajorVersion;       // 0B8  
    ULONG ImageSubsystemMinorVersion;       // 0BC  
    ULONG ImageProcessAffinityMask;         // 0C0  
    ULONG GdiHandleBuffer[0x22];            // 0C4  
    ULONG PostProcessInitRoutine;           // 14C  
    ULONG TlsExpansionBitmap;               // 150  
    UCHAR TlsExpansionBitmapBits[0x80];     // 154  
    ULONG SessionId;                        // 1D4    
} PEB, *PPEB;
好了有了TEB,PEB数据结构的支撑,我们来分析 sub_4018D0()函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
typedef struct _NT_TIB
{                                           // Size: 01C
    struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList; // 000
    PVOID StackBase;                        // 004
    PVOID StackLimit;                       // 008
    PVOID SubSystemTib;                     // 00C
    union                                   // 010
    {
        PVOID FiberData;
        ULONG Version;
    };
    PVOID ArbitraryUserPointer;             // 014
    struct _NT_TIB *Self;                   // 018
} NT_TIB, *PNT_TIB;
  
typedef struct _TEB 
{                                           // Size:  FBC
    NT_TIB Tib;                             // 000
    PVOID EnvironmentPointer;               // 01C
    CLIENT_ID Cid;                          // 020
    PVOID ActiveRpcHandle;                  // 028
    PVOID ThreadLocalStoragePointer;        // 02C
    struct _PEB *ProcessEnvironmentBlock;   // 030
    ULONG LastErrorValue;                   // 034
    ULONG CountOfOwnedCriticalSections;     // 038
    PVOID CsrClientThread;                  // 03C
    struct _W32THREAD* Win32ThreadInfo;     // 040
    ULONG User32Reserved[0x1A];             // 044
    ULONG UserReserved[5];                  // 0AC
    PVOID WOW32Reserved;                    // 0C0
    LCID CurrentLocale;                     // 0C4
    ULONG FpSoftwareStatusRegister;         // 0C8
    PVOID SystemReserved1[0x36];            // 0CC
    LONG ExceptionCode;                     // 1A4
    struct _ACTIVATION_CONTEXT_STACK *ActivationContextStackPointer; // 1A8
    UCHAR SpareBytes1[0x28];                // 1AC    
    GDI_TEB_BATCH GdiTebBatch;              // 1D4    
    CLIENT_ID RealClientId;                 // 6B4    
    PVOID GdiCachedProcessHandle;           // 6BC    
    ULONG GdiClientPID;                     // 6C0
    ULONG GdiClientTID;                     // 6C4    
    PVOID GdiThreadLocalInfo;               // 6C8    
    ULONG Win32ClientInfo[62];              // 6CC    
    PVOID glDispatchTable[0xE9];            // 7C4    
    ULONG glReserved1[0x1D];                // B68    
    PVOID glReserved2;                      // BDC    
    PVOID glSectionInfo;                    // BE0    
    PVOID glSection;                        // BE4    
    PVOID glTable;                          // BE8    
    PVOID glCurrentRC;                      // BEC    
    PVOID glContext;                        // BF0    
    NTSTATUS LastStatusValue;               // BF4    
    UNICODE_STRING StaticUnicodeString;     // BF8    
    WCHAR StaticUnicodeBuffer[0x105];       // C00    
    PVOID DeallocationStack;                // E0C    
    PVOID TlsSlots[0x40];                   // E10    
    LIST_ENTRY TlsLinks;                    // F10    
    PVOID Vdm;                              // F18    
    PVOID ReservedForNtRpc;                 // F1C    
    PVOID DbgSsReserved[0x2];               // F20    
    ULONG HardErrorDisabled;                // F28    
    PVOID Instrumentation[14];              // F2C    
    PVOID SubProcessTag;                    // F64    
    PVOID EtwTraceData;                     // F68    
    PVOID WinSockData;                      // F6C    
    ULONG GdiBatchCount;                    // F70    
    BOOLEAN InDbgPrint;                     // F74    
    BOOLEAN FreeStackOnTermination;         // F75    
    BOOLEAN HasFiberData;                   // F76    
    UCHAR IdealProcessor;                   // F77    
    ULONG GuaranteedStackBytes;             // F78    
    PVOID ReservedForPerf;                  // F7C    
    PVOID ReservedForOle;                   // F80    
    ULONG WaitingOnLoaderLock;              // F84    
    ULONG SparePointer1;                    // F88    
    ULONG SoftPatchPtr1;                    // F8C    
    ULONG SoftPatchPtr2;                    // F90    
    PVOID *TlsExpansionSlots;               // F94    
    ULONG ImpersionationLocale;             // F98    
    ULONG IsImpersonating;                  // F9C    
    PVOID NlsCache;                         // FA0    
    PVOID pShimData;                        // FA4    
    ULONG HeapVirualAffinity;               // FA8    
    PVOID CurrentTransactionHandle;         // FAC
    PTEB_ACTIVE_FRAME ActiveFrame;          // FB0    
    PVOID FlsData;                          // FB4    
    UCHAR SafeThunkCall;                    // FB8    
    UCHAR BooleanSpare[3];                  // FB9
} TEB, *PTEB; 
  
typedef struct _LIST_ENTRY
{                                           // Size: 008
    struct _LIST_ENTRY *Flink;              // 000 从前到后
    struct _LIST_ENTRY *Blink;              // 004 从后到前
} LIST_ENTRY, *PLIST_ENTRY;
  
typedef struct _PER_LDR_DATA
{                                           // Size: 0024
    ULONG Length;                           // 000
    BOOLEAN Initialize;                     // 004
    PVOID SsHandle;                         // 008
    LIST_ENTRY InLoadOrderModuleList;       // 00C
    LIST_ENTRY InMemoryOrderModuleList;     // 014
    LIST_ENTRY InInitializationOrderModuleList; // 01C
} PER_LDR_DATA, *PPER_LDR_DATA;
  
typedef struct _UNICODE_STRING 
{                                           // Size: 008
  USHORT  Length;                           // 000 占用的内存字节数,个数*2;
  USHORT  MaximumLength;                    // 002
  PWSTR  Buffer;                            // 004
} UNICODE_STRING ,*PUNICODE_STRING;
  
typedef struct _LDR_DATA_TABLE_ENTRY
{                                           // Size: 050
     LIST_ENTRY InLoadOrderLinks;           // 000 LIST_ENTRY里的Flink和Blink其实是指向LDR_MODULE结构,即LDR_DATA_TABLE_ENTRY
     LIST_ENTRY InMemoryOrderLinks;         // 008 同上
     LIST_ENTRY InInitializationOrderLinks; // 010 同上
     PVOID DllBase;                         // 018
     PVOID EntryPoint;                      // 01C
     ULONG SizeOfImage;                     // 020
     UNICODE_STRING FullDllName;            // 024
     UNICODE_STRING BaseDllName;            // 02C
     ULONG Flags;                           // 034
     WORD LoadCount;                        // 038
     WORD TlsIndex;                         // 03A
     union                                  // 03C
     {
          LIST_ENTRY HashLinks;             // 03C
          struct
          {
               PVOID SectionPointer;        // 03C
               ULONG CheckSum;              // 040
          };
     };
     union
     {
          ULONG TimeDateStamp;              // 044
          PVOID LoadedImports;              // 044
     };
     _ACTIVATION_CONTEXT * EntryPointActivationContext; // 048
     PVOID PatchInformation;                // 04C
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
  
typedef struct _PEB  
{                                           // Size: 1D8   
    UCHAR InheritedAddressSpace;            // 000  
    UCHAR ReadImageFileExecOptions;         // 001  
    UCHAR BeingDebugged;                    // 002   
    UCHAR SpareBool;                        // 003 Allocation size  
    HANDLE Mutant;                          // 004   
    HINSTANCE ImageBaseAddress;             // 008 
    struct _PER_LDR_DATA *Ldr;              // 00C
    strcut _RTL_USER_PPROCESS_PARAMETERS *ProcessParameters; // 010  
    ULONG SubSystemData;                    // 014  
    HANDLE DefaultHeap;                     // 018  
    KSPIN_LOCK FastPebLock;                 // 01C  
    ULONG FastPebLockRoutine;               // 020  
    ULONG FastPebUnlockRoutine;             // 024  
    ULONG EnvironmentUpdateCount;           // 028  
    ULONG KernelCallbackTable;              // 02C  
    LARGE_INTEGER SystemReserved;           // 030  
    struct _PER_FREE_BLOCK *FreeList;       // 038
    ULONG TlsExpansionCounter;              // 03C  
    ULONG TlsBitmap;                        // 040  
    LARGE_INTEGER TlsBitmapBits;            // 044  
    ULONG ReadOnlySharedMemoryBase;         // 04C  
    ULONG ReadOnlySharedMemoryHeap;         // 050  
    ULONG ReadOnlyStaticServerData;         // 054 
    ULONG AnsiCodePageData;                 // 058  
    ULONG OemCodePageData;                  // 05C  
    ULONG UnicodeCaseTableData;             // 060  
    ULONG NumberOfProcessors;               // 064   
    LARGE_INTEGER NtGlobalFlag;             // 068 Address of a local copy  
    LARGE_INTEGER CriticalSectionTimeout;   // 070  
    ULONG HeapSegmentReserve;               // 078  
    ULONG HeapSegmentCommit;                // 07C  
    ULONG HeapDeCommitTotalFreeThreshold;   // 080  
    ULONG HeapDeCommitFreeBlockThreshold;   // 084  
    ULONG NumberOfHeaps;                    // 088  
    ULONG MaximumNumberOfHeaps;             // 08C  
    ULONG ProcessHeaps;                     // 090  
    ULONG GdiSharedHandleTable;             // 094  
    ULONG ProcessStarterHelper;             // 098  
    ULONG GdiDCAttributeList;               // 09C  
    KSPIN_LOCK LoaderLock;                  // 0A0  
    ULONG OSMajorVersion;                   // 0A4  
    ULONG OSMinorVersion;                   // 0A8  
    USHORT OSBuildNumber;                   // 0AC  
    USHORT OSCSDVersion;                    // 0AE  
    ULONG OSPlatformId;                     // 0B0  
    ULONG ImageSubsystem;                   // 0B4  
    ULONG ImageSubsystemMajorVersion;       // 0B8  
    ULONG ImageSubsystemMinorVersion;       // 0BC  
    ULONG ImageProcessAffinityMask;         // 0C0  
    ULONG GdiHandleBuffer[0x22];            // 0C4  
    ULONG PostProcessInitRoutine;           // 14C  
    ULONG TlsExpansionBitmap;               // 150  
    UCHAR TlsExpansionBitmapBits[0x80];     // 154  
    ULONG SessionId;                        // 1D4    
} PEB, *PPEB;
好了有了TEB,PEB数据结构的支撑,我们来分析 sub_4018D0()函数
1
2
3
4
5
6
7
int sub_4018D0()
{
  int v0; // edx
 
  sub_4018F5(0x3BD696F4);
  return sub_401928(v0, 0x925DF53F);
}
0x3BD696F4是目标字串hash值,继续分析 sub_4018F5()
1
2
3
4
5
6
7
int sub_4018D0()
{
  int v0; // edx
 
  sub_4018F5(0x3BD696F4);
  return sub_401928(v0, 0x925DF53F);
}

[注意]看雪招聘,专注安全领域的专业人才平台!

最后于 2018-12-13 11:59 被ODPan编辑 ,原因:
收藏
免费 4
支持
分享
赞赏记录
参与人
雪币
留言
时间
PLEBFE
为你点赞~
2022-7-27 01:52
心游尘世外
为你点赞~
2022-7-26 23:49
飘零丶
为你点赞~
2022-7-17 03:23
Editor
为你点赞~
2018-12-24 15:49
最新回复 (7)
雪    币: 914
活跃值: (2678)
能力值: ( LV5,RANK:68 )
在线值:
发帖
回帖
粉丝
2
好有趣啊
2018-12-13 14:39
0
雪    币: 9
活跃值: (230)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
3
有意思  一定得找个时间研究一番
2018-12-13 22:03
0
雪    币: 9
活跃值: (230)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
4
有意思  一定得找个时间研究一番
2018-12-13 22:03
0
雪    币: 9
活跃值: (230)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
5
有意思  一定得找个时间研究一番
2018-12-13 22:04
0
雪    币: 9
活跃值: (230)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
6
有意思  一定得找个时间研究一番
2018-12-13 22:04
0
雪    币: 9
活跃值: (230)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
7
有意思  一定得找个时间研究一番
2018-12-13 22:05
0
雪    币: 97
活跃值: (162)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
8
看懂最后那个算法,应该是一个怎样的循序渐进的过程呢?多去研究算法就可以吗?
2018-12-14 22:33
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册