`
dq630dq
  • 浏览: 14198 次
社区版块
存档分类
最新评论

C# 外挂入门 配套 实例+视频 教程

 
阅读更多

C# 外挂入门 配套 实例+视频 教程
2010年06月25日
  // 交流 QQ 406050799  (加我也没用我会的就这点)
  /*
  做外挂我也是现学的。可以说写的这个教程是现学现卖,希望对用C#的外挂爱好者能有点帮助。
  * 有错误希望大家指出来我怕耽人子弟
  第一课:先说下本教程用C#做该挂的原理!(也算不上什么c#了 就几个 winApi)
  1、 通过一些汇编调试工具(OllyICE、Cheat Engine)得到指定应用程序(游戏)的一些内存数据 包括{某些值在内存中存放的位置 比如人物的血 和
  应用程序(游戏)所作动作的函数的位置 比如按f1是攻击那么 按下f1必然会调用一个攻击函数这里叫做call}
  上面的工具得到的是反汇编就是把机器码搞成汇编 所以你需要懂一点汇编
  2、 通过我们写的程序去访问\调用 我们所找到的地址。比如单机游戏 人物的血值 你通过工具找到它在内存的地址 那么你想让血为1万  你就通过你写的程序修改这个内存地址的值为10000 就可以了
  具体怎么做呢?  首先c#是做不到地 但是c#有个很好的靠山 就是win api  我们通过c#调用winApi来对内存操作
  第二课:一些汇编调试工具(OllyICE、Cheat Engine)的用法
  在这里我也就不说明了   我会提供视频教程下载地址     
  1、OllyICE 视频:   (由于压缩包有点大 老是上传不了,过几天我会搞定的) 
  2、ce 视频:    (由于压缩包有点大 老是上传不了,过几天我会搞定的) 
  3、C# 实例+调试使用小程序: http://www.ghoffice.com/bbs/down.php?tid=79095&aid=47126&name=%CD%E2%B9%D2%C1%B7%CF%B0.rar
  第三课:通过第二课我们可以得到应用程序(游戏)中我们想要的内存地址了
  接下来是我这段列子的 步骤
  1、申明WinApi函数   为什么要申明WinApi函数? 答:上面说了 做外挂需要用的一些操作内存的函数 而c#没有 所以要用到win api
  2、看应用程序(游戏)是否启动   -为什么要判断应用程序(游戏)是否启动? 答:如果没有启动应用程序(游戏)  你写的程序(外挂)操作的对象都没有了,你的代码就没意义了。。
  3、得到应用程序(游戏)的进程句柄   -为什么要得到进程句柄 ? 答:应为在对内存地址操作时 必须知道要你操作的是哪个进程范围内的内存地址
  4、读取内存地址内的值   -比如读出游戏人物(角色的血和名字等...)
  5、修改内存中的值
  6、调用应用程序(游戏)内的函数(call)   主要是通过winapi向制定的进程中注入机器码
  下面请看代码(为了方便我就把代码写在一个页面了)
  */
  using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Data;
  using System.Drawing;
  using System.Linq;
  using System.Text;
  using System.Windows.Forms;
  using System.Threading;//多线程命名空间
  using System.Runtime.InteropServices;//申明 WinApi 关键词DllImport的命名空间
  namespace 外挂练习
  {
  public partial class Form1 : Form
  {
  #region 申明WinApi函数
  //下面先看下WinApi是如何引用的
  /*        
  -------------------------------------------------------看下面
  /// 
  /// 函数功能
  /// 
  /// 参数
  /// 参数
  /// 参数
  /// 参数
  /// 参数
  /// 返回值
  ------------------------------------------------------上面们明白吧是对某个函数的说明吧
  ------------------------------------------------------看下面
  [DllImport("kernel32.dll"), EntryPoint = "ReadProcessMemory")]   这里是用于指明 要应用的api所在的dll文件和api(函数名)
  public static extern int ReadProcessMemory(                      这里是申明函数
  IntPtr hProcess,                                             定义参数1
  int lpBaseAddress,                                           定义参数2
  int[] lpBuffer,                                              定义参数3
  int nSize,                                                   定义参数4
  int lpNumberOfBytesWritten                                   定义参数5           关于参数信息你可以去看msdn
  );
  -----------------------------------------------------上面就引用了一个装在kernel32.dll文件下名为 ReadProcessMemory 的 api(函数)
  * 下面关于api的说明自己去看msdn
  */
  #region 申明WinApi函数
  [DllImport("kernel32.dll", EntryPoint = "OpenProcess")]
  public static extern IntPtr OpenProcess(
  Int32 dwDesiredAccess,
  Int32 bInheritHandle,
  int dwProcessId
  );
  /// 
  /// 读写内存
  /// 
  /// 进程,如果你是做外挂的话,它代表你要挂的那个游戏。
  /// 你要读取的内存地址
  /// 从上面那个参数地址里读出来的东西(调用这个函数的就是为了它)  不管这个参数是什么类型,它应该是一个数组,否则读不出东西来 }
  /// /长度,上一个参数,类型是int,那个长度应该用
  /// 用0就行了,想知道它是干嘛的,自己去MSND吧 
  /// 
  [DllImport("kernel32.dll")]
  public static extern int ReadProcessMemory(
  IntPtr hProcess,
  int lpBaseAddress,
  int[] lpBuffer,
  int nSize,
  int lpNumberOfBytesWritten
  );
  [DllImport("kernel32.dll")]
  public static extern int ReadProcessMemory(
  IntPtr hProcess,
  int lpBaseAddress,
  byte[] lpBuffer,
  int nSize,
  int lpNumberOfBytesWritten
  );
  [DllImport("Kernel32.dll")]
  public static extern Int32 VirtualAllocEx(
  IntPtr hProcess,
  Int32 lpAddress,
  int dwSize,
  Int32 flAllocationType,
  Int32 flProtect
  );
  [DllImport("kernel32.dll")]
  public static extern IntPtr WriteProcessMemory(
  IntPtr hProcess,
  Int32 lpBaseAddress,
  [In, Out] byte[] buffer,
  int size,
  Int32 lpNumberOfBytesWritten
  );
  [DllImport("kernel32.dll")]
  public static extern IntPtr WriteProcessMemory(
  IntPtr hProcess,
  Int32 lpBaseAddress,
  int buffer,
  int size,
  Int32 lpNumberOfBytesWritten
  );
  /// 
  ///
  /// 
  /// 目标进程的句柄
  /// 指向线程的安全描述结构体的指针,一般设置为NULL,表示使用默认的安全级别
  /// 线程堆栈大小,一般设置为0,表示使用默认的大小,一般为1M
  /// 线程函数的地址
  /// 线程参数
  /// 线程的创建方式 CREATE_SUSPENDED 线程以挂起方式创建
  /// 输出参数,记录创建的远程线程的ID
  /// 
  [DllImport("kernel32", EntryPoint = "CreateRemoteThread")]
  public static extern int CreateRemoteThread(
  IntPtr hProcess,
  Int32 lpThreadAttributes,
  Int32 dwStackSize,
  Int32 lpStartAddress,
  Int32 lpParameter,
  Int32 dwCreationFlags,
  ref int lpThreadId
  );
  [DllImport("kernel32")]
  public static extern int WaitForSingleObject(
  int hProcess,
  UInt32 lpThreadAttributes
  );
  [DllImport("Kernel32.dll")]
  public static extern System.Int32 VirtualFreeEx(
  IntPtr hProcess,
  Int32 lpAddress,
  int dwSize,
  int flAllocationType
  );
  [DllImport("kernel32.dll", EntryPoint = "CloseHandle")]
  public static extern int CloseHandle(
  int hObject
  );
  #endregion
  #endregion
  #region 成员
  /// 
  /// 申明一个进程 {和外挂没有关系 只是我这里用了循环去读 应用程序(游戏)内的信息 所以的单独用个进程来做这个事 不然会造成 (死循环程序死掉) }
  /// 
  Thread thred;
  /// 
  /// 申明一个全局变量来保存  得到的应用程序(游戏)的进程id
  /// 
  int ProcessID;
  /// 
  /// 申明一个全局变量来保存  得到的应用程序(游戏)的进程句柄
  /// 
  IntPtr process;
  #endregion
  public Form1()
  {
  InitializeComponent();
  }
  private void Form1_Load(object sender, EventArgs e)
  {
  Control.CheckForIllegalCrossThreadCalls = false;//取消线程保护 应为我用了多线程 我在子线程里面修改主线程的东西 在c# 默认是不可以的 所以我这里 是= false(不保护)
  #region 判读应用程序(游戏)是否启动
  System.Diagnostics.Process[] GamesProcess = System.Diagnostics.Process.GetProcessesByName("F8_CALL_04"); //得到名字 为“F8_CALL_04” 的所有进程
  //System.Diagnostics.Process是.NET里的进程类,GetProcessesByName静态方法是通过进程的名字获得进程数组。这行语句执行之后,所有游戏进程就放在了GamesProcess里面。
  if (GamesProcess.Length 这个函数是不停得读内存地址里面的值
  thred.Start();//启动线程
  getstrname();//读取字符串
  }
  #region 读取应用程序(游戏)内存地址内的值
  //读int
  private void WriteMemory()
  {
  int[] xx = new int[1];//声明变量存放存放 api函数从内存中得到的值(x坐标)   为什么要转为int[] 应为Api WriteProcessMemory 的第3个参数要用数组
  int[] yy = new int[1];//声明变量存放存放 api函数从内存中得到的值(y坐标)   为什么要转为int[] 应为Api WriteProcessMemory 的第3个参数要用数组
  while (true) //循环
  {
  ReadProcessMemory(process, 0x462D04, xx, 4, 0);//读取process进程内462D04内存地址中的值 放在xx中   462D04是个16进制 在C#里我们在前面加0x表示   最后2个参数是 读取长度4 表示是int 0不知道是什么东西自己去查一下嘛
  //ReadProcessMemory是个api函数他的作用就是读取内存中的值
  x.Text = xx[0].ToString();//把得到的值让空间x显示出来
  ReadProcessMemory(process, 0x462d08, yy, 4, 0);//读取process进程内462d08内存地址中的值 放在yy中   462d08是个16进制 在C#里我们在前面加0x表示   最后2个参数是 读取长度4 表示是int 0不知道是什么东西自己去查一下嘛
  //ReadProcessMemory是个api函数他的作用就是读取内存中的值
  y.Text = yy[0].ToString();//把得到的值让空间y显示出来
  /*
  在这里这大家需要注意的是地址与指针的偏移  上面我的的地址是写的固定的其实是不对的 正确的用法是 基地址加上偏移量  !看下面   
  来写一段读取诛仙人物HP的代码。首先,我们需要知道人物HP的地址,(废话:如何知道这个地址,用CE还是IE,你自己搞定吧。)我是用IE在这里http://www.ghoffice.com/bbs/read.php?tid-35908-fpage-2.html找到的,它这里是这样写的:
  人物基址:[[&H12F830]+&H28]=base
  生命:[base+&H254]
  (注:&H表示16进制,在C#里我们用0x表示)
  一对[]表示读一次地址。也就是说123表示值123,而[123]就表示从地址123读出来的值。几对[],就要用几次ReadProcessMemory,我们来写下代码:
  int[] Base=new int[1];
  int[] hp=new int[1];
  ReadProcessMemory(process, 0x12F830, Base;, 4, 0);//相当于Base=[&H12F830]
  ReadProcessMemory(process, Base+0x28, Base;, 4, 0);//相当于Base=[Base+&H28]
  //读出了人物基址base
  ReadProcessMemory(process, Base+0x254, hp;, 4, 0);//相当于hp=[base+&H254]
  //读出了hp
  怎么样,很简单吧。
  我们读HP只用了3行ReadProcessMemory。有的时候,读某个值可能需要很多对[],就要写N行ReadProcessMemory,这样写起来就很麻烦,看起来也很晕。下面我们来写个函数,让读内存的过程看起来和[]表示法差不多。
  //为了看起来好看,函数的名字最好短些,所以我们用r,表示read
  public static int r(int add)
  {
  int[] r=new int[1];
  try
  {
  ReadProcessMemory(process, add, r, 4, 0); }
  return r[0];
  }
  catch (Exception ex)
  {
  return -1;
  }
  }
  这个函数很简单,不用我多说了吧。
  有了这个函数,上面的读取HP的代码,我们就可以写成这样了:
  int Base;
  int hp;
  Base=r(r(0x12F830)+0x28);
  //读出了人物基址base );
  hp=r(base+&H254);
  //读出了hp
  看起来清晰多了吧。
  */          
  }
  }
  //读文本
  private void getstrname()
  {
  byte[] nn = new byte[256];//声明变量存放存放函数的到的值(文本)
  ReadProcessMemory(process, 0xACAA44, nn, 256, 0);//读取process进程内ACAA44内存地址中的值 放在nn中   ACAA44是个16进制 在C#里我们在前面加0x表示
  string temp = System.Text.Encoding.Default.GetString(nn); //读出的byte[]要按某种方式编码为字符串 这里用的是 Default
  names.Text = temp.Split('\0')[0].ToString();//截取第一段字符串 给name控件显示
  }
  #endregion
  #region 修改内存中的值
  private void button2_Click(object sender, EventArgs e)
  {
  byte[] nn = System.Text.Encoding.Default.GetBytes(name.Text);//这里是把字符串转为byte[]  为什么要转为byte[] 在前面也说了Api WriteProcessMemory 的第3个参数必须是数组
  WriteProcessMemory(process, 0xACAA44, nn, nn.Length, 0);//用Api WriteProcessMemory 修改process进程中0xACAA44内存中的值 为nn变量里面的值
  getstrname();//修改后重新获取
  }
  #endregion
  #region 调用应用程序(游戏)内的函数(call)主要是通过winapi向制定的进程中注入机器码
  //按钮事件
  private void button1_Click(object sender, EventArgs e)
  {
  #region 得到机器码1
  /*                
  下面是我通过OllyICE找到的汇编代码  简单分析下
  0045AA16  |.  E8 555DFCFF   call    F8_CALL_.00420770
  0045AA1B  |.  5B            pop     ebx
  0045AA1C  \.  C3            retn
  0045AA1D      8D40 00       lea     eax, dword ptr ds:[eax]          这里有个参数
  0045AA20  /.  55            push    ebp
  0045AA21  |.  8BEC          mov     ebp, esp
  0045AA23  |.  8B15 042D4600 mov     edx, dword ptr ds:[462D04]       ;  ds:[00462D04]=00000068
  0045AA29  |.  8915 142D4600 mov     dword ptr ds:[462D14], edx       ;  edx=00000068
  0045AA2F  |.  8B15 082D4600 mov     edx, dword ptr ds:[462D08]       ;  ds:[00462D08]=00000041
  0045AA35  |.  8915 182D4600 mov     dword ptr ds:[462D18], edx       ;  edx=00000041
  0045AA3B  |.  8B4D 08       mov     ecx, dword ptr ss:[ebp+8]        ;  这里有个参数(y)
  0045AA3E  |.  8B55 0C       mov     edx, dword ptr ss:[ebp+C]        ;  这里有个参数(x)
  0045AA41  |.  E8 B6000000   call    F8_CALL_.0045AAFC                这里是个 call(函数)
  0045AA46  |.  5D            pop     ebp
  0045AA47  \.  C2 0C00       retn    0C
  -----------------------------------------------------------------
  0045AAF7   .  C3            retn
  0045AAF8   .  00002041      dd      float 10.00000
  0045AAFC  /$  53            push    ebx
  0045AAFD  |.  8BD8          mov     ebx, eax               这里把eax给了ebx----------看下面
  0045AAFF  |.  8915 1C2D4600 mov     dword ptr ds:[462D1C], edx 这里是个参数               |
  0045AB05  |.  890D 202D4600 mov     dword ptr ds:[462D20], ecx 这里是个参数               ↓
  0045AB0B  |.  8BC3          mov     eax, ebx               这里----------- 又把ebx 放在了eax里
  0045AB0D  |.  E8 D6FDFFFF   call    F8_CALL_.0045A8E8
  0045AB12  |.  B2 01         mov     dl, 1
  0045AB14  |.  8B83 68030000 mov     eax, dword ptr ds:[ebx+368]
  0045AB1A  |.  E8 C511FDFF   call    F8_CALL_.0042BCE4
  --------------
  * 通过上面分析可以得到函数0045AAFC有3个有用参数(eax、ecx、edx)还原成汇编如下
  pushad
  mov     ecx, 100   
  mov     edx, 100
  mov     eax, 00A77170
  call    0045AAFC
  popad
  ret
  然后再把这段汇编代码放在这个工具 (汇编转机器码(new))中 转换   这个工具有些是用方法会在下载的工具包内有说明
  转换后会得到类似60bdfcaa4500b964000000ba64000000bb7071a700b87071a700ffd561c3的字符串,大家可以用下面的getBytes2方法把它转换为byte[]
  如下代码
  */
  #endregion
  byte[] bytes = getBytes2("60bdfcaa4500b964000000ba64000000b87071a700ffd561c3");  //bytes就是我们要的 所谓的机器码
  #region 使用得到机器码
  Int32 addr = VirtualAllocEx(process, 0, bytes.Length, 0x1000, 0x40);//一,申请空间
  WriteProcessMemory(process, addr, bytes, bytes.Length, 0);//二,把代码写进去
  int hThread = CreateRemoteThread(process, 0, 0, addr, 0, 0, ref ProcessID);//三,执行写入的代码
  WaitForSingleObject(hThread, 0xFFFFFFFF);//等待线程结束
  VirtualFreeEx(process, addr, 0, 0x8000); //四,释放申请的空间
  CloseHandle(hThread);//五,关闭线程句饼          
  #endregion
  }
  private void button3_Click(object sender, EventArgs e)
  {
  #region 得到带参数的机器码
  /*
  关于参数:
  你可以把参数放到汇编里,转成机器码。然后再换个参数,在转机器码。
  观察机器码的区别,有区别的地方就是放参数的地方。
  观察的时候注意,机器码里的数字是两位为单位,倒序排列的,
  比如转之前,汇编代码里有12345678,转后的机器码里就一定能找到78563412.
  然后你就可以在自己的程序里,以字符串连接方式,处理带参数机器码。
  如:把下面的汇编放入工具
  pushad
  mov ebp,0045AAFC
  mov     ecx, 100      
  mov     edx, 100    
  mov     ebx, 00A77170
  mov     eax, 00A77170
  call    ebp
  popad
  ret
  得到的字符串是60bdfcaa4500b964000000ba64000000bb7071a700b87071a700ffd561c3 然后我把第一个100换成123把第二个100换成456 再放入工具
  得到的字符串是60bdfcaa4500b97b000000ba7b000000bb7071a700b87071a700ffd561c3
  仔细观察会发现第一个64000000变成了7b000000
  第二个64000000变成了c8010000
  这就说明这个2个地方是放参数的
  问题又来了参数位置得到了  那么参数要以什么格式的字符串格式加上去呢?
  先将用户输入的值转为16进制 然后通过getByte函数处理16进制就得到了我们想要的字符串了
  看下面代码
  */
  string xx = string.Empty;//定义变量存放用户输入值 的16进制
  string yy = string.Empty;//定义变量存放用户输入值 的16进制
  try
  {
  xx = Convert.ToString(int.Parse(x2.Text), 16);//将用户输入的值装换为16进制
  yy = Convert.ToString(int.Parse(y2.Text), 16);//将用户输入的值装换为16进制
  }
  catch
  {
  MessageBox.Show("请输入正确坐标!");
  return;
  }
  xx = getByte(xx);//把16进制装换为我们需要的字符串
  yy = getByte(yy);//把16进制装换为我们需要的字符串
  #endregion
  byte[] bytes = getBytes2("60bdfcaa4500b9" + yy + "ba" + xx + "b87071a700ffd561c3");//我们要写入的代码(这里我调用的是F8_CALL_04 中 方块移动的函数传了2个参数  x和y)               
  #region 使用得到机器码
  Int32 addr = VirtualAllocEx(process, 0, bytes.Length, 0x1000, 0x40);//一,申请空间
  WriteProcessMemory(process, addr, bytes, bytes.Length, 0);//二,把代码写进去
  int hThread = CreateRemoteThread(process, 0, 0, addr, 0, 0, ref ProcessID);//三,执行写入的代码
  WaitForSingleObject(hThread, 0xFFFFFFFF);//等待线程结束
  VirtualFreeEx(process, addr, 0, 0x8000); //四,释放申请的空间
  CloseHandle(hThread);//五,关闭线程句饼
  #endregion
  }
  #endregion
  #region 内部方法
  //移位 补位函数
  public static string getByte(string HEX)
  {
  string hex = string.Empty;
  HEX = "0" + HEX;
  for (int i = 2; HEX.Length >= i; i += 2)
  {
  if (HEX.Length%2==0)
  {
  hex += HEX.Substring(HEX.Length - i,2);
  }
  else
  {
  hex += HEX.Substring(HEX.Length - i,1);
  }
  }
  while (hex.Length <
  { hex += "0"; }
  return hex;
  }
  public static byte[] getBytes2(string HEX)
  {
  byte[] bytes = new byte[HEX.Length / 2];
  for (int i = 0; i < bytes.Length; i++)
  {
  bytes = Convert.ToByte(Int32.Parse(HEX.Substring(i * 2 , 2),
  System.Globalization.NumberStyles.AllowHexSpecifier));
  }
  return bytes;
  }
  //关闭清空
  private void Form1_FormClosed(object sender, FormClosedEventArgs e)
  {
  if (thred != null)
  thred.Abort();
  }
  #endregion
  }
  }
分享到:
评论

相关推荐

    198个经典C#WinForm实例源码+C#入门必看的实例程序100个

    198个经典C#WinForm实例源码+C#入门必看的实例程序100个

    C#从入门到精通 第3版 原书配套光盘资源下载

    C#从入门到精通 第3版 原书配套光盘资源下载

    《Visual C#.NET范例入门与提高》实例1~~3章

    《Visual C#.NET范例入门与提高》配套光盘使用说明 本书所附光盘的内容包含了开发实例的所有程序源码,所有程序源码都是在Win2000 Professional,Visual C#.NET环境下编译并运行通过。要运行本光盘上的实例,用户应...

    C#入门到精通详细资料文档

    1、C#入门到精通详细资料文档 2、C#详细入门及编程实例文档

    198个经典C#WinForm实例源码

    198个经典C#WinForm实例源码 1、窗体 2、控件 3、图像 4、报表 5、系统 6、文件 7、网络 8、数据库 9、加密、解密 10、硬件读写

    《Visual C#.NET范例入门与提高》实例8章

    《Visual C#.NET范例入门与提高》配套光盘使用说明 本书所附光盘的内容包含了开发实例的所有程序源码,所有程序源码都是在Win2000 Professional,Visual C#.NET环境下编译并运行通过。要运行本光盘上的实例,用户应...

    C#编程宝典(十年典藏版).pdf

    《C#编程宝典(十年典藏版)》附有配套DVD光盘,光盘中提供了书中全部实例和项目的源代码,这些源代码全部经过精心调试,能够在Windows XP、Windows Server 2003以及Windows 7操作系统下编译和运行。 《C#编程宝典(十...

    《Visual C#.NET范例入门与提高》实例4~~7章

    《Visual C#.NET范例入门与提高》配套光盘使用说明 本书所附光盘的内容包含了开发实例的所有程序源码,所有程序源码都是在Win2000 Professional,Visual C#.NET环境下编译并运行通过。要运行本光盘上的实例,用户应...

    C#编程网络大讲堂图书教程

    本书全面介绍C#编程知识,全书共分4篇18章,内容包括:C#基础入门篇(第1~9章),介绍C#的开发环境和基础知识;C#实际应用篇(第10~12章),介绍创建Windows窗体应用程序和各类Windows控件的使用,MDI程序设计,...

    《Visual C#.NET范例入门与提高》实例 第9章

    《Visual C#.NET范例入门与提高》配套光盘使用说明 本书所附光盘的内容包含了开发实例的所有程序源码,所有程序源码都是在Win2000 Professional,Visual C#.NET环境下编译并运行通过。要运行本光盘上的实例,用户应...

    vc++ 开发实例源码包

    视频教程步骤源码 DDraw DirectX 实例 DES加密算法源代码 如题。 Detected memory leaks 检查内存泄漏源码 DigiStatic_src 自绘CStatic实现数字效果。 DirectShow开发指南pdf附属代码 如题。 DirectShow开发...

    面向对象C#初级入门精讲(1)C#开发入门

    【课程特色】1、课程设计循序渐进、讲解细致、通俗易懂、非常适合自主学习2、教学过程实例丰富、强调技术关键点、并且分析透彻此外,提供源代码+配套练习+答疑+上课日志。欢迎加入QQ群538724338提问,这样老师能及时...

    Visual C# 2005全程指南光盘

     本书主要适用于初中级的Visual C#2005用户,最后的“Visual C# 2005网络编程技术”以及“Windows线程的高级编程知识”也适用于高级用户使用,为了方便读者的学习,本书在配套光盘中存放了所有本书的实例。

    Visual C# 2005全程指南 李建华 源代码

    本书主要适用于初中级的Visual C#2005用户,最后的“Visual C# 2005网络编程技术”以及“Windows线程的高级编程知识”也适用于高级用户使用,为了方便读者的学习,本书在配套光盘中存放了所有本书的实例。

    Visual C#2005全程指南(18-22章)

    本书主要适用于初中级的Visual C# 2005用户,最后的“Visual C# 2005网络编程技术”以及“Windows线程的高级编程知识”也适用于高级用户使用,为了方便读者的学习,本书在配套光盘中存放了所有本书的实例。

    visual c#2005全程指南(8-12章)

    本书主要适用于初中级的Visual C# 2005用户,最后的“Visual C# 2005网络编程技术”以及“Windows线程的高级编程知识”也适用于高级用户使用,为了方便读者的学习,本书在配套光盘中存放了所有本书的实例

    visual c#2005全程指南(5-7章)

    本书主要适用于初中级的Visual C# 2005用户,最后的“Visual C# 2005网络编程技术”以及“Windows线程的高级编程知识”也适用于高级用户使用,为了方便读者的学习,本书在配套光盘中存放了所有本书的实例。

    visual c#2005全程指南(第一章)

    本书主要适用于初中级的Visual C# 2005用户,最后的“Visual C# 2005网络编程技术”以及“Windows线程的高级编程知识”也适用于高级用户使用,为了方便读者的学习,本书在配套光盘中存放了所有本书的实例。

    visual c#2005全程指南(13-17章)

    本书主要适用于初中级的Visual C# 2005用户,最后的“Visual C# 2005网络编程技术”以及“Windows线程的高级编程知识”也适用于高级用户使用,为了方便读者的学习,本书在配套光盘中存放了所有本书的实例。

    C#入门精讲7C#常用类

    【教学理念】?1、把“需要工作的人”变成“工作需要的人”?2、创设“立足学生、突出项目、强化技术、提高...2、教学过程实例丰富、强调技术关键点、并且分析透彻?3、物美价廉此外,提供源代码+配套练习+答疑+上课日志。

Global site tag (gtag.js) - Google Analytics