CVE-2021-39863 Analysis
CVE-2021-39863
- ์ํฅ์ ๋ฐ๋ ์ ํ : https://helpx.adobe.com/security/products/acrobat/apsb21-55.html
- Exploit์๋ 32bit Adobe Acrobat Reader DC 21.005.20048.43252 ๋ฒ์ ์ ์ฌ์ฉํ์๋ค.
- ํด๋น ์ ํ์ ์๋ ๋งํฌ์์ ๋ค์ด ๋ฐ์ ์ ์๋ค.
- https://ardownload2.adobe.com/pub/adobe/reader/win/AcrobatDC/2100520048/AcroRdrDC2100520048_en_US.exe
1. ์ทจ์ฝํ ํจ์ ์ฐพ๊ธฐ
- URL ์ฐ๊ฒฐ ๊ณผ์ ์์ ๋ฐ์ํ๋ ์ทจ์ฝ์ ์ด๊ธฐ์ Adobe Acrobat Reader DC์ IA32.api๋ฅผ IDA๋ก ์ ์ ๋ถ์์ ์งํํ๋ค.
- ์ฐธ๊ณ ํ Exploit ์๋ฃ์๋ ์ทจ์ฝํ ํจ์ ์ฐพ๋ ๋ฐฉ๋ฒ์ด ๋๋ฝ๋์ด 3๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ์ทจ์ฝํ ํจ์๋ฅผ ์ฐพ์๋ค.
-
์ทจ์ฝํ ํจ์๋ฅผ ์ฐพ์ ๋ฐฉ๋ฒ
1) ์ํธ ์ฐธ์กฐ
- [Exodus Blog](https://blog.exodusintel.com/2021/10/04/analysis-of-a-heap-buffer-overflow-vulnerability-in-adobe-acrobat-reader-dc-2/?utm_source=feedly&utm_medium=rss&utm_campaign=analysis-of-a-heap-buffer-overflow-vulnerability-in-adobe-acrobat-reader-dc-2)์์ ํ์ธํ ๊ฒฐ๊ณผ ์ทจ์ฝํ ํจ์๊ฐ ํธ์ถํ ํจ์๋ URL ์ฐ๊ฒฐ์ ์ํด `strncat` ํจ์๋ฅผ ํธ์ถํ๋ค.
strncat
ํจ์๋ ์ธ๋ถ์์ importํด ์ฌ์ฉํ๋ค.- ์ธ๋ถ์์ importํ ํจ์๋ ํด๋น ํจ์์ ์ด๋ฆ์
.rdata
์์ญ์ ์ ์ฅํด ํธ์ถํ ๋ ์ด์ฉํ๋ค.
- ์ธ๋ถ์์ importํ ํจ์๋ ํด๋น ํจ์์ ์ด๋ฆ์
- [๊ทธ๋ฆผ 1]๊ณผ [๊ทธ๋ฆผ 2]์ฒ๋ผ
.rdata
์์ญ์์"strncat"
๋ฌธ์์ด์ ์ฐพ์ ์ทจ์ฝํ ํจ์๊ฐ ๋์ฌ ๋๊น์ง ์ํธ์ฐธ์กฐํ์๋ค.
[๊ทธ๋ฆผ 1] .rdata ์์ญ์์
"strncat"
๋ฌธ์์ด์ ํ์ธํ๊ณ ,strncat
ํจ์์ ์ํธ ์ฐธ์กฐ ํจ์๋ฅผ ํ์ธํ ๋ชจ์ต[๊ทธ๋ฆผ 2] [๊ทธ๋ฆผ 10]์์ ์ฐพ์
strncat
ํจ์์ ์ํธ ์ฐธ์กฐ ํจ์์ ์ํธ ์ฐธ์กฐ ํจ์๋ฅผ ํ์ธํ ๋ชจ์ต
2) OpCode ๊ฒ์
-
- ์ทจ์ฝํ ํจ์์์๋ UTF16-BE encoding์ ํ์งํ๊ธฐ ์ํด UTF16-BE BOM ๊ฒ์ฌ๋ฅผ ์งํํ๋ค.
- ๋ํ์ ์ผ๋ก 1 byte ๊ฐ๊ณผ
"\xFF"
๋น๊ตํ๋ ์ฐ์ฐ์ ์ํํ๋ค.
"\xFF"
์ 1 byte ๋ ์ง์คํฐ๋ฅผ ๋น๊ตํ๋ OP Code๋ฅผ ์ป์ด, ํด๋น OP Code๊ฐ ์กด์ฌํ๋ ํจ์๋ฅผ ํ์ํ๋ฉฐ ์ทจ์ฝํ ํจ์๋ฅผ ์ฐพ์๋ค.
[๊ทธ๋ฆผ 3] OpCode ๊ฒ์ฌ๋ก ์ทจ์ฝํ ํจ์๋ฅผ ์ฐพ์ ๋ชจ์ต
4) IDC IDA Script ์ด์ฉ
-
Exodus ๋ธ๋ก๊ทธ๋ฅผ ํ์ด๋ณธ ๊ฒฐ๊ณผ, ์ทจ์ฝํ ํจ์๋ ๋ง์ ๋ช ๋ น์ ๋ณด์ ํ๊ณ ์๋ ๊ฒ์ ํ์ธํ์๋ค. ์ด๋ฅผ ํ ๋๋ก instruction ์๋ก ํจ์๋ฅผ ํ์ํ๋ฉด ์ทจ์ฝํ ํจ์๋ฅผ ์ฝ๊ฒ ์ฐพ์ ์ ์์ผ๋ฆฌ๋ผ ํ๋จํ๋ค.
-
IDA์ ๋ด์ฅ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ธ IDC๋ก ํน์ instruction ์ ์ด์์ ํจ์๋ฅผ ์ฐพ๋ script๋ฅผ ์์ฑํด ์ทจ์ฝํ ํจ์๋ฅผ ์ฐพ์๋ค.
#include <idc.idc> static main() { auto func, end, count, inst; func = 0; Message("================ START =================\n"); for(func = NextFunction(func); func != BADADDR; func = NextFunction(func)) { if(func != -1) { end = GetFunctionAttr(func, FUNCATTR_END); count = 0; inst = func; while(inst < end) { count++; inst = FindCode(inst, SEARCH_DOWN | SEARCH_NEXT); } if(count > 400) { Message("%s contains %d instructions\n" , Name(func), count); } } else { //Message("No function found at location %x", func); } } }
[๊ทธ๋ฆผ 4] IDC IDA Script๋ก ์ทจ์ฝํ ํจ์๋ฅผ ์ฐพ์ ๋ชจ์ต
2. ์ทจ์ฝํ ํจ์ ๋ถ์
์ทจ์ฝํ ํจ์๋ฅผ ๋์ปดํ์ผํ ์ฝ๋
__int16 __cdecl ExploitPoint(wchar_t *Source, CHAR *lpString, char *String, _DWORD *a4, int *a5)
{
__int16 v5; // di
wchar_t *concatURL_addr; // ebx
CHAR *lpString_copy; // eax
CHAR v8; // dl
__int64 len_lpString; // rax
wchar_t *Source_copy; // ecx
__int64 len_Source; // rax
int v12; // eax
int totallen_Source; // eax
int len_Source_notUTF; // eax
CHAR *allocadr_Source; // eax
wchar_t *v16; // ecx
int totallen_lpString; // eax
int len_lpString_notUTF; // eax
CHAR *allocadr_lpString; // eax
int v20; // eax
int v21; // edx
int v22; // edx
_DWORD *v23; // eax
int v24; // ecx
int *v25; // eax
int v26; // ecx
int v27; // eax
int v28; // ecx
int v29; // eax
wchar_t *v30; // ecx
int v31; // eax
int len_allocaddr; // eax
int v33; // eax
int v34; // ecx
int v35; // edx
wchar_t *v37; // [esp-4h] [ebp-F4h]
unsigned int v38; // [esp-4h] [ebp-F4h]
wchar_t *v39; // [esp-4h] [ebp-F4h]
unsigned int v40; // [esp-4h] [ebp-F4h]
unsigned int v41; // [esp-4h] [ebp-F4h]
int v42[7]; // [esp+Ch] [ebp-E4h] BYREF
int v43; // [esp+28h] [ebp-C8h]
int v44; // [esp+2Ch] [ebp-C4h]
int v45; // [esp+30h] [ebp-C0h]
int v46; // [esp+34h] [ebp-BCh]
wchar_t *v47; // [esp+38h] [ebp-B8h]
__int64 v48; // [esp+3Ch] [ebp-B4h]
int v49; // [esp+4Ch] [ebp-A4h]
int v50[3]; // [esp+50h] [ebp-A0h] BYREF
int v51; // [esp+5Ch] [ebp-94h]
int v52; // [esp+60h] [ebp-90h]
int v53; // [esp+64h] [ebp-8Ch]
int v54; // [esp+68h] [ebp-88h]
int v55; // [esp+6Ch] [ebp-84h]
int v56; // [esp+70h] [ebp-80h]
int v57; // [esp+74h] [ebp-7Ch]
int v58; // [esp+78h] [ebp-78h]
char *v59; // [esp+7Ch] [ebp-74h]
__int64 v60; // [esp+80h] [ebp-70h]
__int64 v61; // [esp+88h] [ebp-68h]
int v62; // [esp+90h] [ebp-60h]
int v63[3]; // [esp+94h] [ebp-5Ch] BYREF
int v64; // [esp+A0h] [ebp-50h]
int v65; // [esp+A4h] [ebp-4Ch]
int v66; // [esp+A8h] [ebp-48h]
int v67; // [esp+ACh] [ebp-44h]
int v68; // [esp+B0h] [ebp-40h]
int v69; // [esp+B4h] [ebp-3Ch]
int v70; // [esp+B8h] [ebp-38h]
int v71; // [esp+BCh] [ebp-34h]
void *v72; // [esp+C0h] [ebp-30h]
__int128 v73; // [esp+C4h] [ebp-2Ch]
int v74; // [esp+D4h] [ebp-1Ch]
int iMaxLength[2]; // [esp+D8h] [ebp-18h]
LPCSTR allocadr_lpString_copy; // [esp+E0h] [ebp-10h]
LPCSTR allocadr_Source_copy; // [esp+E4h] [ebp-Ch]
int v78[2]; // [esp+E8h] [ebp-8h] BYREF
allocadr_Source_copy = 0;
allocadr_lpString_copy = 0;
v5 = 1;
*(_QWORD *)v78 = 0i64;
*(_QWORD *)iMaxLength = 0i64;
concatURL_addr = 0;
v49 = 0;
v62 = 0;
v74 = 0;
if(!a5) return 0;
*a5 = 0;
// [1-1] relative URL ๊ธธ์ด ์ธก์
lpString_copy = lpString;
if(lpString && *lpString && (v8 = lpString[1]) != 0 && *lpString == (CHAR)0xFE && v8 == (CHAR)0xFF) {
len_lpString = ((__int64 (__cdecl *)(CHAR *))strlen_UTF16BE)(lpString);
v78[1] = len_lpString;
if ((HIDWORD(len_lpString)&(unsigned int)len_lpString) == -1) {
LABEL_9:
*a5 = -2;
return 0;
}
lpString_copy = lpString;
} else {
v78[1] = v78[0];
}
// [1-2] base URL ๊ธธ์ด ์ธก์
Source_copy = Source;
if(!Source || !lpString_copy || !String || !a4) {
*a5 = -2;
goto LABEL_86;
}
if(*(_BYTE *)Source != 0xFE) goto LABEL_25;
if(*((_BYTE *)Source+1) == 0xFF) {
len_Source = ((__int64 (__cdecl *)(wchar_t *))strlen_UTF16BE)(Source);
iMaxLength[1] = len_Source;
if((HIDWORD(len_Source)&(unsigned int)len_Source) == -1) goto LABEL_9;
Source_copy = Source;
v12 = iMaxLength[1];
} else {
v12 = iMaxLength[0];
}
if(*(_BYTE *)Source_copy == 0xFE && *((_BYTE *)Source_copy+1) == 0xFF) {
totallen_Source = v12 + 2;
} else {
LABEL_25:
len_Source_notUTF = (int)custom_strlen((LPCSTR)Source_copy);
Source_copy = v37;
totallen_Source = len_Source_notUTF + 1;
}
iMaxLength[1] = totallen_Source;
// [2-1] base URL์ ์๋ก์ด heap์ ์ ์ฅ
allocadr_Source = (CHAR *)((int (__usercall *)@<eax>(wchar_t *@<ecx>, int, int))calloc_guess)(Source_copy, 1, totallen_Source);
allocadr_Source_copy = allocadr_Source;
if(!allocadr_Source) {
*a5 = -7;
return 0;
}
((void (__usercall *)(unsigned int@<ecx>, wchar_t *, wchar_t *, int))custom_strncpy)(v38, (wchar_t *)allocadr_Source, Source, iMaxLength[1]);
if(*lpString==(CHAR)0xFE && lpString[1]==(CHAR)0xFF) {
totallen_lpString = v78[1] + 2;
} else {
len_lpString_notUTF = (int)custom_strlen(lpString);
v16 = v39;
totallen_lpString = len_lpString_notUTF + 1;
}
v78[1] = totallen_lpString;
// [2-2] relative URL์ ์๋ก์ด heap์ ์ ์ฅ
allocadr_lpString = (CHAR *)((int (__usercall *)@<eax>(wchar_t *@<ecx>, int, int))calloc_guess)(v16, 1, totallen_lpString);
allocadr_lpString_copy = allocadr_lpString;
if(!allocadr_lpString) {
*a5 = -7;
LABEL_86:
v5 = 0;
goto LABEL_87;
}
((void (__usercall *)(unsigned int@<ecx>, wchar_t *, wchar_t *, int))custom_strncpy)(v40, (wchar_t *)allocadr_lpString, (wchar_t *)lpString, v78[1]);
if(!(unsigned __int16)check_modify_URL((int)allocadr_Source_copy, iMaxLength[1], a5) || !(unsigned __int16)check_modify_URL((int)allocadr_lpString_copy, v78[1], a5)) {
goto LABEL_86;
}
// [3] URL ๊ด๋ จ ์ฐ์ฐ ์ํ
v20 = URLparse_process((CHAR *)allocadr_Source_copy, v42);
if(v20 || (v20 = URLparse_process((CHAR *)allocadr_lpString_copy, v50)) != 0) {
*a5 = v20;
goto LABEL_86;
}
if(!*(_BYTE *)Source || (v21 = v42[0], v50[0] != 5) && v50[0] != v42[0]) {
v35 = sub_25802FAC((int)v50);
v23 = a4;
v24 = v35 + 1;
if(v35 + 1 > *a4) goto LABEL_44;
*a4 = v35;
v25 = v50;
goto LABEL_82;
}
if(*lpString) {
v26 = v55;
v63[1] = v42[1];
v63[2] = v42[2];
v27 = v51;
v63[0] = v42[0];
v73 = 0i64;
if(!v51 && !v53 && !v55) {
if(sub_25803155(v50)) {
v28 = v44;
v64 = v42[3];
v65 = v42[4];
v66 = v42[5];
v67 = v42[6];
v29 = v43;
if(v49 == 1) {
v29 = v43 + 2;
v28 = v44 - 1;
v43 += 2;
--v44;
}
v69 = v28;
v68 = v29;
v70 = v45;
if(v58) {
if (*v59 != '/') {
// [4] ์ฐ๊ฒฐ๋ URL์ ์ ์ฅํ๊ธฐ ์ํ ์๋ก์ด heap ํ ๋น
concatURL_addr = (wchar_t *)((int (__usercall *)@<eax>(wchar_t *@<ecx>, int, int))calloc_guess)((wchar_t *)(v58 + 1), 1, v58 + 1 + v46);
if(!concatURL_addr) {
v23 = a4;
v24 = v58 + v46 + 1;
goto LABEL_44;
}
if(v46) {
// [5] base URL์ [4]์์ ํ ๋นํ heap memory์ ์ ์ฅ
((void (__usercall *)(unsigned int@<ecx>, wchar_t *, wchar_t *, int))custom_strncpy)(v41, concatURL_addr, v47, v46 + 1);
if (*((_BYTE *)concatURL_addr + v46 - 1) != '/') {
v31 = ((int (__usercall *)@<eax>(wchar_t *@<ecx>, char *, int))sub_25818D6E)(v30, (char *)concatURL_addr, '/');
if(v31) *(_BYTE *)(v31 + 1) = 0;
else *(_BYTE *)concatURL_addr = 0;
}
}
// [6] relative URL์ [5]์์ ์ ์ฅํ base URL ๋ค์ ์ด์ด ๋ถ์ : ์ทจ์ฝ์ ๋ฐ์
if(v58) {
len_allocaddr = (int)custom_strlen((LPCSTR)concatURL_addr);
((void (__usercall *)(uintptr_t@<ecx>, char *, char *, int))custom_strncat)(v58 + 1, (char *)concatURL_addr, v59, v58 + 1 + len_allocaddr);
}
sub_25802E0C((int)concatURL_addr, 0);
v71 = (int)custom_strlen((LPCSTR)concatURL_addr);
v72 = concatURL_addr;
goto LABEL_75;
}
v71 = v58;
v72 = v59;
} else {
v71 = v46;
v72 = v47;
if((_DWORD)v60) goto LABEL_75;
*(_QWORD *)&v73 = v48;
}
LABEL_74:
if((_DWORD)v73) {
LABEL_77:
if ( (int)v61 > 0 ) *((_QWORD *)&v73 + 1) = v61;
v34 = sub_25802FAC((int)v63);
if(v34+1 > *a4) {
*a4 = v34 + 1;
goto LABEL_45;
}
*a4 = v34;
v25 = v63;
goto LABEL_82;
}
LABEL_75:
if((int)v60 > 0) *(_QWORD *)&v73 = v60;
goto LABEL_77;
}
v26 = v55;
v21 = v42[0];
v27 = v51;
}
v64 = v27;
v65 = v52;
v66 = v53;
v67 = v54;
v33 = v56;
if(v62 == 1) {
v26 += 2;
v33 = v56 - 1;
v55 = v26;
--v56;
}
v69 = v33;
v68 = v26;
v71 = v58;
v70 = v57;
v72 = v59;
if(v57) goto LABEL_75;
v78[1] = 0;
if(!sub_25802C93(v21, &v78[1])) goto LABEL_75;
v70 = v78[1];
goto LABEL_74;
}
v22 = sub_25802FAC((int)v42);
v23 = a4;
v24 = v22 + 1;
if(v22+1 > *a4) {
LABEL_44:
*v23 = v24;
LABEL_45:
*a5 = -3;
goto LABEL_86;
}
*a4 = v22;
v25 = v42;
LABEL_82:
sub_25803194((int)v25, String);
LABEL_87:
if(allocadr_Source_copy)
(*(void (__cdecl **)(LPCSTR))(dword_25824098 + 12))(allocadr_Source_copy);
if(allocadr_lpString_copy)
(*(void (__cdecl **)(LPCSTR))(dword_25824098 + 12))(allocadr_lpString_copy);
if(concatURL_addr)
(*(void (__cdecl **)(wchar_t *))(dword_25824098 + 12))(concatURL_addr);
return v5;
}
Root Cause๋ฅผ ์ดํดํ๋ ๋ฐ ์๋์ ํจ์๋ค์ ์ดํดํด์ผ ํ๋ค.
- ExploitPoint() : ๋ถ์์ ์์ ํจ์
- Parameter
- _BYTE *Source : baseURL
- _BYTE *lpString : relative URL
- Exploit์ ํ์ํ ๋ถ๋ถ๋ง ๋ํ๋ด๋ฉด ํฌ๊ฒ ์๋์ ๋์์ ๊ฑฐ์น๋ค.
-
URL ๊ธธ์ด ์ธก์
[1-1] relative URL ๊ธธ์ด ์ธก์ [1-2] base URL ๊ธธ์ด ์ธก์ -
URL์ heap์ ์ ์ฅ
[2-1] base URL์ ์๋ก์ด heap์ ์ ์ฅ [2-2] relative URL์ ์๋ก์ด heap์ ์ ์ฅ -
URL ๊ด๋ จ ์ฐ์ฐ ์ํ(Exploit๊ณผ ์ง์ ์ ์ธ ์ฐ๊ด์ ์๋ค.) -
์ฐ๊ฒฐ๋ URL์ ์ ์ฅํ๊ธฐ ์ํ ์๋ก์ด heap ํ ๋น
-
base URL์ [4]์์ ํ ๋นํ heap memory์ ์ ์ฅ
-
relative URL์ [5]์์ ์ ์ฅํ base URL ๋ค์ ์ด์ด ๋ถ์ : ์ทจ์ฝ์ ๋ฐ์
-
- Parameter
- strlen_UTF16BE : UTF16-BE encoding ๋ฌธ์์ด์ ๊ธธ์ด๋ฅผ ๊ณ์ฐํ๋ค.
- Parameter
- char *string : ๊ธธ์ด๋ฅผ ๊ณ์ฐํ UTF16-BE๋ก encoding๋ ๋ฌธ์์ด
- return value : Null Terminator๋ฅผ ์ ์ธํ UTF16-BE URL์ byte ์
int __cdecl strlen_UTF16BE(char *string) { char *p_string_i0; // eax char string_i1; // cl int length; // esi char string_i0; // bl char *p_string_i1; // eax p_string_i0 = string; if(!string || *string != -2 || string[1] != -1) return -1; string_i1 = 0; length = 0; do { string_i0 = *p_string_i0; p_string_i1 = p_string_i0 + 1; if(!p_string_i1) break; string_i1 = *p_string_i1; p_string_i0 = p_string_i1 + 1; if(!string_i0) goto LABEL_10; if(!string_i1) break; length += 2; } while ( p_string_i0 ); if(string_i0) return -1; LABEL_10: if(!string_i1) return length; else return -1; }
- Parameter
- custom_strlen() : UTF16-BE์์๋ ๋์ํ๋ strlen ํจ์์ด๋ค.
- Parameter
- LPCSTR lpString : UTF-16BE๋ก encoding๋ ๋ฌธ์์ด์ ์ฃผ์ (32 bit)
- return value : Null Terminator๋ฅผ ์ ์ธํ URL์ byte ์
int __cdecl strlen_UTF16BE_(char *string) { char *v1; // ecx int i; // edx char v4; // al v1 = string; if(!string) return 0; for(i = 0; ; i += 2) { v4 = *v1; v1 += 2; if (!v4 && !*(v1-1)) break; } return i; }
- Parameter
- calloc_guess() : C์ calloc ํจ์์ด๋ค.
- custom_strncpy() : UTF16-BE์์๋ ๋์ํ๋ strncpy ํจ์์ด๋ค.
- Parameter
- wchar_t *Destination : ๋ณต์ฌํ ์ฃผ์
- wchar_t *Source : ๋ณต์ฌํ ๋ฌธ์์ด(์ ์ฃผ์)
- unsigned int iMaxLength : ๋ณต์ฌํ ๊ธธ์ด
- return value : deststr (๋ณต์ฌํ ๊ณต๊ฐ; ๋ณต์ฌ๋ ์ฅ์)
wchar_t *__cdecl custom_strncpy(wchar_t *Destination, wchar_t *Source, unsigned int iMaxLength) { wchar_t *result; // eax int pExceptionObject; // [esp+Ch] [ebp-4h] BYREF if(!Destination || !Source || !iMaxLength) { (*(void (__thiscall **)(_DWORD, int))(dword_258240A4 + 4))(*(_DWORD *)(dword_258240A4 + 4), 1073741827); pExceptionObject = 0; CxxThrowException(&pExceptionObject, (_ThrowInfo *)&_TI1H); } if(*(_BYTE *)Source == 0xFE && *((_BYTE *)Source+1) == 0xFF) return wcsncpy(Destination, Source, iMaxLength >> 1); result = (wchar_t *)lstrcpynA((LPSTR)Destination, (LPCSTR)Source, iMaxLength); *((_BYTE *)Destination + iMaxLength - 1) = 0; return result; }
- Parameter
- custom_strncat() : UTF16-BE์์๋ ๋์ํ๋ strncat ํจ์์ด๋ค.
- Parameter
- char *Destination, char *Source, int maxlength
- Destination ๋ค์ Source๋ฅผ ๋ถ์
- ์ ์์ ์ธ ๊ฒฝ์ฐ ๋ ๋ฒ์งธ if ๋ฌธ์ ํตํด custom_strcat(Destination, Source); ํธ์ถ
int __cdecl custom_strncat(char *Destination, char *Source, int maxlength) { int result; // eax LPCSTR pExceptionObject; // [esp+10h] [ebp-4h] BYREF if(!Destination || !Source || !maxlength) { (*(void (__thiscall **)(_DWORD, int))(dword_258240A4 + 4))(*(_DWORD *)(dword_258240A4 + 4), 1073741827); pExceptionObject = 0; CxxThrowException(&pExceptionObject, (_ThrowInfo *)&_TI1H); } pExceptionObject = custom_strlen(Destination); if(&custom_strlen(Source)[(int)pExceptionObject] <= (const CHAR *)(maxlength-1)) { custom_strcat(Destination, Source); return 1; } else { strncat(Destination, Source, maxlength - (_DWORD)pExceptionObject - 1); result = 0; Destination[maxlength - 1] = 0; } return result; }
- Parameter
- custom_strcat() : UTF16-BE์์๋ ๋์ํด์ผ ํ๋ strcat ํจ์๋ก ์ง์ ์ ์ผ๋ก ์ทจ์ฝ์ ์ด ๋ฐ์ํ๋ค.
- Parameter
- LPSTR lpString1 : base URL
- LPCSTR lpString2 : relative URL
- base URL์ด UTF16-BE๋ก encoding ๋์์ ๊ฒฝ์ฐ, base URL ๋ค์
"\x00\x00"
์ด ๋์ฌ ๋๊น์ง relative URL์ 2 byte ์ฉ ๋ณต์ฌํ๋ค.- ์ฆ, relative URL์ด UTF16-BE๋ก encoding ๋์๋ค๊ณ ์ธ์ํ๊ณ ์ฐ๊ฒฐ์ ์งํํ๋ค.
- base URL์ด UTF16-BE๋ก encoding ๋์ง ์์์ ๊ฒฝ์ฐ, lstrcatA ํจ์๋ฅผ ํธ์ถํด
"\x00"
์ด ๋์ฌ ๋๊น์ง base URL ๋ค์ relative URL์ 1 byte ์ฉ ๋ณต์ฌํ๋ค.- ์ฆ, relative URL๋ UTF16-BE๋ก encoding ๋์ง ์์๋ค๊ณ ์ธ์ํ๊ณ ์ฐ๊ฒฐ์ ์งํํ๋ค.
LPSTR __cdecl custom_strcat(LPSTR lpString1, LPCSTR lpString2) { int len_lpString1; // eax LPCSTR p_lpString2_i2; // edx CHAR *concatpoint; // ecx CHAR lpString2_i2; // al CHAR lpString2_i3; // bl int pExceptionObject; // [esp+10h] [ebp-4h] BYREF if(!lpString1 || !lpString2) { (*(void (__thiscall **)(_DWORD, int))(dword_258240A4 + 4))(*(_DWORD *)(dword_258240A4 + 4), 1073741827); pExceptionObject = 0; CxxThrowException(&pExceptionObject, (_ThrowInfo *)&_TI1H); } if(*lpString1 == (CHAR)0xFE && lpString1[1] == (CHAR)0xFF) { len_lpString1 = (int)custom_strlen(lpString1); p_lpString2_i2 = lpString2 + 2; concatpoint = &lpString1[len_lpString1]; do { do { lpString2_i2 = *p_lpString2_i2; p_lpString2_i2 += 2; *concatpoint = lpString2_i2; concatpoint += 2; lpString2_i3 = *(p_lpString2_i2 - 1); *(concatpoint - 1) = lpString2_i3; } while(lpString2_i2); } while(lpString2_i3); } else { lstrcatA(lpString1, lpString2); } return lpString1; }
- Parameter
3. Root Cause
[๊ทธ๋ฆผ 5] Root Cause ๋ชจ์๋
REFERENCE
[1] THE IDA PRO BOOK 2ND EDITION (Chris Eagle)