[转载]向其他程序注入托管程序集

mikel阅读(1050)

[转载]向其他程序注入托管程序集,很强。 – 唯笑志在 – 博客园.

上帝都知道托管程序集,那就必然就是托付管理…没有自主权了.
托管程序调用非托管程序集不外乎通过PInvoke或者COM接口调用.但是托管程 序集调用非托管程序集貌似也只能够通过COM了,至少在现行NET文档是这样子介绍的.虽然NET类库十分强大,大可不必操作平台API即可完成一个出色 的程序或者说程序集,不过有的时候我们还是需要的,特别是我们要操作其他程序行为的时候.
包括实现APi Hook.
穿透防火墙.
甚 至是实现无进程.当然这些在WIN32编程中是非常容易实现的.dotNet要带上一个数十MB的NET包裹,确实难…而且其实际意义…恐怕等到09年 Vista大范围普及的时候用处方能够显著.毕竟Net开发尤其是搞点窗体数据库这些是非常非常容易的.我本人也是非常喜欢dotNet的.
读者 仔细看我的标题会发现我说的是C#代码,而非dotNet代码.为什么呢?因为C#有一个特殊的地方在于它是纯粹的面向对象的语言.根本不提供全局方法. 其次在于.C#我个人或者数大多数人比较喜欢,有一定的代表性,最次的是,我确实无法忍受C++/Clr的开发方式…真的想吐的感觉.当然Vb.net也 不是本文讨论的重点.毕竟我个人还是不太喜欢Nothing这种语法.其实null看起来更专业.
好了废话就不说了.
在WIN32中比较独立的就算是进程了,当然这里没有说COM这些乱七八糟的东西.所以说我们所说的注入莫非也就是注入到别的进程中.
思考一下有些什么方法可以让别的进程加载我们的程序集:
1.  COM,很好的办法.微软在NET对COM的支持还是比较好的
2.  利用C++的Exports DLL功能,这个听起来还不错.
我这里就用第二种方法.第一种为什么不用呢?考虑到WIN32调用COM我不是很熟悉,其次感觉注册过来注册过去的不够环保,也不利于调试.
当然第二种方法偶其实也不算很喜欢…毕竟必须要用C++/Clr的代码.但毕竟还是有一点C++基础也不算太复杂.
实 现的基本思路就是利用C++/Clr或者其他语言甚至是WIN32建立一个注入机程序,然后利用注入机把另一个写好的C++/Clr 的DLL注入到目标 进程并初始化调用,其中这个DLL负责调用CShape的DLL.其实关键就在于中间的那个C++/Clr的DLL.其实整个过程理解起来非常容易.
我 用的远程线程插入的方法注入DLL(这种代码讨论太多了我就略过了),,顺便说说为什么我必须要用一个中转DLL.原因是这样的:在 Visual C++ 2005中MSDN 里面有一段话,大概意思是如果托管代码中用混合编程即含有本机代码,那么EntryPoint必须为本机函 数.这样子无法在初始化的时候调用托管代码,而我的窗体界面已经弄好,,,为了俭省就不去重新写本机的了,本身就算MFC画个窗体也是容易把脑壳搞大…希 望对后人有点帮助这句.
我们的C++/Clr就填充一个输出表
LIBRARY   ClrDllInjectHelper
EXPORTS
LoadCShapeDll
大概就像这个样子,
然后在注入的本机代码中调用
void WINAPI RemoteMain(void * Data)
{
__try
{
LPVOID pProc;
pProc = ::GetProcAddress(LoadLibraryW(DllPath),”LoadCShapeDll”);
if(pProc == NULL)
{
::MessageBoxA(NULL,”无法载入动态连接库,请检查文件完整性;\r\n 注入进程退出”,”错误”,MB_ICONERROR);
::ExitProcess(NULL);
}
__asm
{
lea eax,CShapeDllPath
push eax
call [pProc]
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
::MessageBoxA(NULL,”SEH异常Handlered!!!”,NULL,MB_ICONERROR);
}
//装载自己以加载托管代码
}大概代码就像这样子,我们以正常方式载入一个DLL.这样子这个DLL就可以调用托管程序集
在公开的DLL输出函数中调用
void __stdcall LoadCShapeDll(WCHAR * CShapeDllPath)
{
String ^ str;
try
{

Assembly ^ assembly;
str = ::System::Runtime::InteropServices::Marshal::PtrToStringAuto(System::IntPtr::IntPtr(CShapeDllPath));
assembly = ::Assembly::LoadFile(str);
Type ^ type = assembly->GetType(“CShapeDll.AppMain”);
System::Reflection::MethodInfo ^ mi = type->GetMethod(“Main”);
mi->Invoke(nullptr,nullptr);
}
catch (Exception ^ e)
{
System::Windows::Forms::MessageBox::Show(e->Message + “\r\n DllPath:” + str,”Error Occured When in injection Code”);
::ExitProcess(NULL);
}
// System::Windows::Forms::MessageBox::Show(“Debug”);
}
这样子就可以装载C#程序集
C#程序集我们只需要新建一个类库并且初始化一个静态类
代码向这样.
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
namespace CShapeDll
{
public static class AppMain
{
public static void Main()
{
MessageBox.Show(“Loaded”);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new FormMain());
}
}
public class Class1
{
}
}

即可.理论上非常简单的.这样子我们的任务就完成了.
现在我们来讨论一下为什么可以用C++/Clr输出一个DLL.
我们用OllyDbg加载有全局输出表的DLL.
我们会’惊讶’的发现有标准的输出表

这就意味着我们是完全可以通过这种方式装载托管/非托管代码的.当然我想这是C++之所以强大的原因之一吧.
我们在DLL没有初始化完成之前双击这个函数
会发现
100010D0 C> $- FF25 24800010        jmp dword ptr ds:[10008024]
100010D6       CC                   int3
100010D7       CC                   int3
它会跳到数据段中.而此时代码段中的数据是一个无效指针.当我们初始化DLL完成以后.
这个数据就会被填充.进而转到了Jitter中
79013370     58                     pop eax
79013371     55                     push ebp
79013372     8BEC                   mov ebp,esp
79013374     51                     push ecx
79013375     52                     push edx
79013376     50                     push eax
79013377     E8 87920000            call mscoree.7901C603
7901337C     5A                     pop edx
7901337D     59                     pop ecx
7901337E     5D                     pop ebp
7901337F     50                     push eax
79013380     C3                     retn
.因此.一旦我们用标准的LoadLibraryA/W方式载入了这个动态链接库.用GetProcAddress就可以平常WIN32的形式调用托管代码.这无疑是非常方便的.尤其是非托管要调用托管代码的话.
文章没有任何技术含量.各位看官全当儿戏即可.

源自:【百木破解】向其他程序注入托管程序集,很强。
http://www.bmpj.net/forum-viewthread-tid-254-fromuid-1.html

[转载]调用动态类型的扩展方法

mikel阅读(999)

[转载]调用动态类型的扩展方法 – 麒麟.NET – 博客园.

对于一个动态类型来说,你可以认为它包含任意成员,它们都能通过编译。但到了运行时,到底是否拥有这些成员,就真相大白了。如

dynamic test = 7;
Console.Write(test.Name);

编译器无法在编译时知道test的真正类型,因此会使用其运行时的实际类型,而默认对于它的所有调用都是合法的,不会引发任何编译时错误。但它会抛出一个运行时异常。因为在运行时,test为一个int,它不具备Name属性。

在编译时,编译器会根据会生成一些调用所需的上下文环境,如所有已知的静态类型等。但它无法知道在源代码中究竟引入了哪些命名空间。因此,你无法调用动态类型所代表的实际类型的扩展方法,也无法将动态类型作为参数传入扩展方法。如

dynamic size = 5;
var numbers = Enumerable.Range(1, 10);
var error = numbers.Take(size);

但我们有两种方法可以实现这两点,它们看上去可能有点丑陋,但在你需要的时候却会很有用。这两种方法为:

1. 将动态类型强制转换为已知的符合方法签名的静态类型

2. 以静态方法的形式调用

对于将动态类型作为参数传入扩展方法的情况,你可以这样

dynamic size = 5;
var numbers = Enumerable.Range(1, 10);
var workaround1 = numbers.Take((int)size);
var workaround2 = Enumerable.Take(numbers, size);

对于调用动态类型的扩展方法,可以这样

int size = 5;
dynamic numbers = Enumerable.Range(1, 10);
var workaround1 = ((IEnumerable<int>)numbers).Take(size);
var workaround2 = Enumerable.Take(numbers, size);

怎么样,很简单吧?

这其实是我在阅读Jon Skeet的新书C# in Depth, Second Edition时遇到的问题,当时脑子犯懵有点不能理解,于是想起Jon时常活跃于Stackoverflow,何不发帖问问这个问题?没想到仅仅十几分钟的时间,Jon就给予了解答,甚至有人怀疑我是蓄意为之……而且,更令人开心的是,还得到了博客园的朋友Colin Han的回答。

所以,如果你有什么难题一时无法应对,不妨去求助于Stackoverflow,去咨询一下全世界范围内的高手牛人们,相信你一定会得到满意的答复。

[转载]字符串转换成JSON的三种方式

mikel阅读(1158)

[转载]字符串转换成JSON的三种方式 – Snandy – 博客园.

采用Ajax的项目开发过程中,经常需要将JSON格式的字符串返回到前端,前端解析成JS对象(JSON )。
ECMA-262(E3) 中没有将JSON概念写到标准中,但在 ECMA-262(E5) 中JSON的概念被正式引入了,包括全局的JSON对象和Date的toJSON方法。

1,eval方式解析,恐怕这是最早的解析方式了。

1 function strToJson(str){
2 var json = eval('(' + str + ')');
3 return json;
4 }

记得str两旁的小括号哦。
2,new Function形式,比较怪异哦。

1 function strToJson(str){
2 var json = (new Function("return " + str))();
3 return json;
4 }


3,使用全局的JSON对象。

1 function strToJson(str){
2 return JSON.parse(str);
3 }

目前IE8(S)/Firefox3.5+/Chrome4/Safari4/Opera10 已实现了该方法。

使用JSON.parse需严格遵守JSON规范,如属性都需用引号引起来,如下

1 var str = '{name:"jack"}';
2 var obj = JSON.parse(str); // --> parse error

name没有用引号引起来,使用JSON.parse所有浏览器中均抛异常,解析失败。而前两种方式则没问题。
相关:

http://blogs.msdn.com/ie/archive/2008/09/10/native-json-in-ie8.aspx
https://developer.mozilla.org/en/Using_JSON_in_Firefox

[转载]C#程序抓取网页源码实例(winform程序)

mikel阅读(963)

[转载]C#程序抓取网页源码实例(winform程序)-纯野.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
using System.Collections;

namespace CopyHtml
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
//获取指定网页中的源数据

string rl;
WebRequest Request = WebRequest.Create(textBox1.Text.Trim());

WebResponse Response = Request.GetResponse();

Stream resStream = Response.GetResponseStream();

StreamReader sr = new StreamReader(resStream, Encoding.Default);
StringBuilder sb = new StringBuilder();
while ((rl = sr.ReadLine()) != null)
{
sb.Append(rl);
}
textBox2.Text = sb.ToString();//抓取得到的源网页

string he = textBox2.Text.ToString();

textBox3.Text = stripHtml(he);//去除html标签后得到的源网页

Match TitleMatch = Regex.Match(he, “([^<]*)“, RegexOptions.IgnoreCase | RegexOptions.Multiline);//获取网页的标题
string title = TitleMatch.Groups[1].Value;

textBox4.Text = (“网页的标题是:” + title );

}

///

/// 去掉网页中的html标签
///

/// 待转化的字符串 ///
private string stripHtml(string strHtml)
{
Regex objRegExp = new Regex(“<(.|\n)+?>“);
string strOutput = objRegExp.Replace(strHtml, “”);
strOutput = strOutput.Replace(“<", "<"); strOutput = strOutput.Replace(">“, “>”);
return strOutput;
}

// 提取HTML代码中的网址
public static ArrayList GetHyperLinks(string htmlCode)
{
ArrayList al = new ArrayList();

string strRegex = @”(href)[ ]*=[ ]*[“”‘][^””‘#>]+[“”‘]”;

Regex r = new Regex(strRegex, RegexOptions.IgnoreCase);
MatchCollection m = r.Matches(htmlCode);

for (int i = 0; i <= m.Count - 1; i++) { bool rep = false; string strNew = m[i].ToString(); // 过滤重复的URL foreach (string str in al) { if (strNew == str) { rep = true; break; } } if (!rep) al.Add(strNew); } al.Sort(); return al; } } } [/csharp]

[转载]FlashFXP打造自动镜像更新

mikel阅读(1022)

[转载]FlashFXP打造自动镜像更新 – 电仔的博客 – 博客园.

朋友公司最近又买了一台服务器,但是接入的是电信宽带(原先的服务器是网通宽带),朋友想用电信宽带作为镜像,从原服务器上同步(下载)一些视频文件,而且要能够实现每隔一段时间自动扫描更新的文件,然后进行同步,即使服务器重启了也能够自启动

环境:

网通服务器  Windows 2008 Server、Server-U服务器

电信服务器  Windows 2008 Server R2 64X 、FlashFXP_4.0.0.1510

一开始搜索了晚上的文章,有用网络传神、Web Synchronizer等等各种同步软件。

于是尝试,发现网络神传不能够后台运行,也不能够以服务形式运行,而且只能够定时上传故舍弃~

然后是用Web Synchronizer,发现电信服务器的能够连接到网通服务器的21端口上,但是状态一直停留在Scanning,无法完成同步~~放弃……

之后上网搜索了很多种FTP软件,同步工具,发现都不符合要求, 最后把希望寄托在了FlashFXP上。

笔者使用的是FlashFXP_4.0.0.1510_Crack 绿色又是注册版 挺好用的~

经过尝试发现做如下设置即可实现上述功能:

1、建立一个站点, 我建立的是网通服务器的FTP连接

注意:FTP服务器用户 test对应的目录应该要锁定在预同步目录的上一级目录上

设置完成之后点击应用 ,然后点击连接

2、建立队列

连接到刚刚建立的FTP服务器后,找到要同步的目录,右击该目录,选择队列

然后会在队列区看到 刚才建立的队列

右击队列区的那个队列,另存为 test.fqf

3、编辑文件传输规则

编辑文件传输规则是为了确保每次只更新最新的文件

打开 菜单栏 选项>文件传输规则>添加

添加如下两条规则:

4、建立计划任务

Task Scheduler 必须开启~ 否则会出错哦~

点击菜单栏的工具>计划>新建任务

任务名称 test 队列文件选择刚刚新建的那个队列文件 test.fqf

在计划这个标签里面进行如下设置

然后到Windows标签进行如下设置,确保能够自启动

首先勾空 “只有在用户登录后才运行任务”

然后输入管理员或者能够进行相应操做的用户的用户名和密码

日志等等依据个人习惯自行设置吧~

总结:

这样设置,就能够满足一开始提出的问题。并且能够依托于服务进行更新。

但是有几点需要注意:

如果需要同步的文件夹的文件很多或者文件较大时,则应该把检测的间隔时间调大一点,否则会比较占用资源。

Task Scheduler 必须开启~ 否则会出错哦~

[转载]Android JAVA 语言基础例子代码

mikel阅读(928)

[转载]Android JAVA 语言基础例子代码 – Thinker – 博客园.

Android的界面一般都是java开发的,因此对于c++,.net人员来说理解和编写有一个适应过程,最近参考了一下资料,把这些涉的一些java基础使用以例子代码的形式总结起来,记录了这个平台的熟悉过程。

文件目录(涉及了java的一些主要语法)

AnnotDefine.java
AnnotDemo.java             ClassDemo.java
CodeResource_en_US.java    Collection.java
demo.java                  example_en_US.properties
Generic.java               InitDemo.java
IO.java                    LocalResource.java
Nest.java                  PrefsDemo.java
ThreadDemo.java

下载地址:

http://cid-56b433ad3d1871e3.office.live.com/self.aspx/.Public/AndroidJava.rar

至于JAVA和C#的语法区别,可以参考一个有意思的网站

http://www.harding.edu/fmccown/java_csharp_comparison.html

以下是一些简要的说明(JDK),具体的使用和一些说明参考以上的例子

Collections Framework

包:java.util

接口

核心和层次关系

Iterable, Collection, List, Set, SortedSet, Queue, Map, and SortedMap.

image

实现类

实现类约定:

Abstract开头的是抽象类,用于减少多个实现的代码重复

具体的类以接口的名字结尾,如ArrayList实现的事List接口

如下是JDK中的实现类列表

AbstractCollection, AbstractList, AbstractQueue, AbstractSequentialList, AbstractSet,

ArrayBlockingQueue, ArrayDeque, ArrayList, AttributeList, ConcurrentLinkedQueue, ConcurrentSkipListSet, CopyOnWriteArrayList, CopyOnWriteArraySet, DelayQueue, EnumSet, HashSet, JobStateReasons, LinkedBlockingDeque, LinkedBlockingQueue, LinkedHashSet, LinkedList, PriorityBlockingQueue, PriorityQueue, RoleList, RoleUnresolvedList, Stack, SynchronousQueue, TreeSet, Vector

工具类

数组和容器的遍历方法

Collection<String> col = …

Iterator iter = col.iterator();

while (iter.hasNext())

System.out.println(iter.next());

for (String s: col)

System.out.println(s);

嵌套类型Nested Type

There are four kinds of nested classes: static member classes, nonstatic member classes, anonymous classes, and local classes. The latter three categories are known as inner classes.

注释类型annotations

java.lang

Deprecated
Override
SuppressWarnings

java.lang.annotation

Documented
Inherited
Retention
Target

javax.annotation

Generated
PostConstruct
PreDestroy
Resource
Resources

[转载]为Android安装BusyBox —— 完整的bash shell

mikel阅读(1007)

[转载][Android] 为Android安装BusyBox —— 完整的bash shell – 木乃猫的学习笔记 – 博客园.

大家是否有过这样的经历,在命令行里输入adb shell,然后使用命令操作你的手机或模拟器,但是那些命令都是常见Linux命令的阉割缩水版,用起来很不爽。是否想过在Android上使用较完整 的shell呢?用BusyBox吧。不论使用adb连接设备使用命令行还是在手机上直接用terminal emulator都可以。

一、什么是BusyBox ?

BusyBox 是标准 Linux 工具的一个单个可执行实现。BusyBox 包含了一些简单的工具,例如 cat 和 echo,还包含了一些更大、更复杂的工具,例如 grep、find、mount 以及 telnet。有些人将 BusyBox 称为 Linux 工具里的瑞士军刀.简单的说BusyBox就好像是个大工具箱,它集成压缩了 Linux 的许多工具和命令。(摘自百度百科)

二、在Android上安装BusyBox

准备:

1. 下载BusyBox的binary,打开这个地址 http://www.busybox.net/downloads/binaries ,选择最新版本,然后下载对应你的设备架构的版本,这里我下载了busybox-armv6l,下面将以这个文件名为示例。

2. 需要有一个命令行的环境,在电脑上使用adb或在手机上使用terminal emulator。

3. 连接手机和电脑,手机的USB Mode设置成None(仅充电),并且开启USB调试模式。

安装:

1. 将busybox-armv6l重命名为busybox

2. 将busybox传入手机的SD卡,可以使用下面的命令或自己想其他办法。

打开terminal(Linux,Mac)或cmd(Windows)

adb push ~/Desktop/busybox /mnt/sdcard

其中的~/Desktop请根据自己的情况替换成正确的路径

3. 输入以下命令,为了在/system目录写入文件

adb shell
su
mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system

使用 ls 检查一下 /system 里是否有 xbin 目录,没有的话输入 mkdir xbin 创建,因为本示例是要把busybox安装到 /system/xbin 。

4. 复制 busybox 文件到 /system/xbin,并为其分配“可执行”的权限

cp /mnt/sdcard/busybox /system/xbin
chmod 755 busybox

5. 这时就可以使用 busybox 的命令了,例如以前没有清屏的clear命令,现在只需输入 busybox clear 就可以实现清屏功能,使用完整版的 ls 只需输入 busybox ls 。

但是每次前面都加上个busybox太麻烦了,所以我们还要继续完成安装。

在 /system/xbin 下输入

busybox --install .

如果想安装到别的目录,则把点替换成别的路径。

至此就安装完成了,比较一下原来的 ls 命令和 busybox 里的 ls 命令。

常见错误:

1. 如果安装时出现这样的错误,

busybox: /bin/zcat: No such file or directory

busybox: /sbin/zcip: Invalid cross-device link

说明没有输入安装路径,正确的示例 busybox –install /system/xbin

2. 如果出现这样的错误,

cp: /system/xbin/busybox: Read-only file system

说明没有正确输入上面第三步的mount命令。

小技巧:

1. busybox 里有 ash 和 hush 还有 sh 这几种 shell,在命令行输入 ash 或 hush,可以像在 bash 里那样,通过按上下键选择刚才输入的命令。

2. Android系统本身就有ls命令,busybox里也有ls,输入ls时调用的是android的ls,那么想用busybox的ls就要每次都在前面加个busybox吗?不用,使用alias命令可以搞定。

alias ls='busybox ls'

同样的,cp、mv等二者都有的命令都可以这样搞定。也可以通过修改 /init.rc 来解决。

[转载]推荐14款强大的HTML5素描及绘图工具

mikel阅读(1073)

[转载]推荐14款强大的HTML5素描及绘图工具 – 梦想天空 – 博客园.

我们知道,素描是设计师工作流程中的一个重要环节。本文收集了一些借助 JavaScript和HTML5 Canvas开发的素描工具,这些工具表明,HTML5的确是一个令人兴奋的标记语言。如果你发现了新的基于HTML5 Canvas开发的绘图工具,欢迎在这里与大家分享。

1. Mr. Doob’s Harmony

HTML5 Sketching Tools Every Designers Must Know

如果你喜欢涂鸦,可以试试这款工具,它有各种各样的画笔可用于绘图。

2. Sketch

HTML5 Sketching Tools Every Designers Must Know

一款叫Hakim El Hattab的人开发的一款素描工具,可绘制三维图案。

3. deviantMuro

HTML5 Sketching Tools Every Designers Must Know

一款非常好的用于素描及绘画的工具,有很多强大的功能。

4. Sketchy Structures

HTML5 Sketching Tools Every Designers Must Know

这款绘图工具可以绘制出一些非常特别的场景。

5. Multi-User Sketchpad

HTML5 Sketching Tools Every Designers Must Know

一款支持多人同时在线绘画的工具。

6. Sketchpad

HTML5 Sketching Tools Every Designers Must Know

一款非常棒的绘画工具,看起来很炫啊。

7. Bezier Sketching

HTML5 Sketching Tools Every Designers Must Know

贝塞尔素描工具,最大的特色是定义路径。

8. Gartic Canvas Sketch

HTML5 Sketching Tools Every Designers Must Know

另一款基于WEB的绘图工具。

9. Spirograph

HTML5 Sketching Tools Every Designers Must Know

可以画出很炫的圆形图案的工具。

10. Bomomo

HTML5 Sketching Tools Every Designers Must Know

一款让人惊叹的绘图工具,想了解更多,请访问Bomomo’s gallery.

11. Internet Graffiti Board

HTML5 Sketching Tools Every Designers Must Know

每个人都可以使用的涂鸦板,即时保存和发布。

12. Pschiiit

HTML5 Sketching Tools Every Designers Must Know

这是一个网络涂鸦板的增强版,图案以多边形形式存储在PostGreSQL数据库中。

13. physicSketch

HTML5 Sketching Tools Every Designers Must Know

你在画布上绘制的图形会以重力效应运动。

14. Zwibbler

HTML5 Sketching Tools Every Designers Must Know

另一款基于HTML5 Canvas开发的绘图程序。

(编译来源:梦想天空 原文来自:HTML5 Sketching Tools Every Designers Must Know

[转载]如何使用C#实现网易博客中圈子用户数据的采集

mikel阅读(1138)

[转载]如何使用C#实现网易博客中圈子用户数据的采集 – wuhuacong(伍华聪)的专栏 – 博客园.

新浪博客,网易博客,都是博客中的佼佼者,其中网易提供的圈子信息,更胜一筹,使得一般用户能够通过访问圈子进入相关的群组,或者获取相关圈子用户 的信息等,以实现各种精准营销的目的。虽然新浪遮遮掩掩不提供圈子的相关信息,相对而言,网易博客提供圈子,能够使得更多的人、更多的程序支持,推高博客 的知名度及实用性。网易博客可以通过地址http://q.163.com/ 访问,它是经过两级分类的,如下所示。

点击分类进入即可查看到每个子分类都有很多圈子,圈子累死QQ的群组,是某一兴趣团体的博客,里面收集很多相关的资料及信息,如下所示:

这里不关心圈子的有哪些宝贵学习资料,我更关心的是这些圈子的用户如何采集出来,由于用户都是网易的用户,因此他们一个账户就会对应一个账号,有163.com,163.net,yeah.net,126.com等等的,我们先看看圈子的用户信息是如何显示的。

我们看到上图里面圈子的信息是一个列表,有的圈子多,有的圈子少,不过他们的名称中都会关联一个博客地址的,由于博客地址和邮件地址有一一对应关系,因此可以获取对应的邮件信息,这就是我们所要的重要信息。

下面用一个程序来介绍如何采集圈子的分类、圈子数据以及圈子用户资料信息,测试的程序如下所示:

下面我们来看看按钮”刷新分类数据“的实现代码,主要是获取圈子大类、圈子子类以及保存数据操作,代码如下所示:

private void btnRefreshCategory_Click(object sender, EventArgs e)
{
string url = http://q.163.com/;
string mainTypeReg = <div\\s*style=\”font-size:14px;\”><b><a\\s*?href=\”(?<value>.*?)\”>(?<key>.*?)</a></b></div>;
string subTypeReg = <div\\s*class=\”left\”><a\\s*href=\”(?<value>.*?)\”>(?<key>.*?)</a></div> ;

#region 取得大类

httpHelper.Encoding = Encoding.Default;
string content = httpHelper.GetHtml(url);
Regex re
= new Regex(mainTypeReg, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace);
Match mc
= re.Match(content);
Dictionary
<string, string> typeDict = new Dictionary<string, string>();
if (mc.Success)
{
MatchCollection mcs
= re.Matches(content);
foreach (Match me in mcs)
{
string strKey = me.Groups[key].Value;
string strValue = me.Groups[value].Value;
//截取连接前面部分作为大类标识
string newValue = strValue.TrimEnd(/);
int eIndex = newValue.LastIndexOf(/);
newValue
= newValue.Substring(0, eIndex) + /;

if (!typeDict.ContainsKey(strKey))
{
typeDict.Add(strKey, newValue);
}
}
}
#endregion

#region 取得子类
Dictionary
<string, CircleSubTypeInfo> circleDict = new Dictionary<string, CircleSubTypeInfo>();
re
= new Regex(subTypeReg, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace);
mc
= re.Match(content);
if (mc.Success)
{
MatchCollection mcs
= re.Matches(content);
foreach (Match me in mcs)
{
string strKey = me.Groups[key].Value;
string strValue = me.Groups[value].Value;
//截取连接前面部分作为大类标识
string typeValue = strValue.TrimEnd(/);
int eIndex = typeValue.LastIndexOf(/);
typeValue
= typeValue.Substring(0, eIndex) + /;

if (!circleDict.ContainsKey(strKey))
{
CircleSubTypeInfo info
= new CircleSubTypeInfo();
info.Name
= strKey;
info.LinkUrl
= strValue;
info.TypeUrlValue
= typeValue;

circleDict.Add(strKey, info);
}
}
}
#endregion

#region 保存数据
Database db
= DatabaseFactory.CreateDatabase();
DbCommand command
= null;
string SQL = “”;

foreach (string key in typeDict.Keys)
{
SQL
= string.Format(Insert into CircleType(TypeName, TypeValue) values(‘{0}’, ‘{1}’) , key, typeDict[key]);
command
= db.GetSQLStringCommand(sql);
db.ExecuteNonQuery(command);
}

foreach (string key in circleDict.Keys)
{
CircleSubTypeInfo info
= circleDict[key];
sql
= string.Format(Insert into CircleSubType(SubTypeName, LinkUrl, TypeUrlValue) values(‘{0}’, ‘{1}’, ‘{2}’) , info.Name, info.LinkUrl, info.TypeUrlValue);
command
= db.GetSqlStringCommand(sql);
db.ExecuteNonQuery(command);
}
#endregion

this.lblTips.Text = 获取分类操作完成;

}


其中主要是采用了正则表达式来对获取的内容进行处理,然后整理出来相关的分类数据放到数据库中,以便获取圈子用户信息作准备。

有了圈子分类信息,我们第二步骤就是看如何获取圈子数据,然后才能通过圈子的唯一ID获取圈子的用户资料,这步也是必须的,获取圈子资料是比较复杂的,需要组装较多的参数获取资料,部分代码如下所示。

foreach (string key in urlDict.Keys)
{
string keyNumberReg = /mapCircleList/(?<d1>[1-9]\\d*)/(?<d2>[1-9]\\d*)*/(?<d3>[1-9]\\d*)/;
Regex re
= new Regex(keyNumberReg, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace);

LogTextHelper.WriteLine(string.Format(正在处理类型:{0}, urlDict[key]));
cookie
= new System.Net.CookieContainer();

string urlKey = key;
Match mc
= re.Match(urlKey);
string d1 = mc.Groups[d1].Value;
string d2 = mc.Groups[d2].Value;
string d3 = mc.Groups[d3].Value;
int pageSize = 30;

urlKey = urlKey.Trim(/);//清除前后的/字符
string url = http://q.163.com/dwr/call/plaincall/CircleMainpageBean.getCircleByType2IdInMemberOrder.dwr;
//string refUrl = “http://q.163.com/mapCircleList/2/11/48/?fromCircleCircleMap“;
string refUrl = string.Format(http://q.163.com/{0}/?fromCircleCircleMap, urlKey);
#region 内容正则表达式
StringBuilder circleReg
= new StringBuilder();
circleReg.Append(
s[0-9]\\d*.circleId=(?<circleId>[0-9]\\d*[^;]));
circleReg.Append(
.*?s[0-9]\\d*.circleType1Str=\”(?<circleType1Str>.*?)\”);
circleReg.Append(
.*?s[0-9]\\d*.circleType2Str=\”(?<circleType2Str>.*?)\”);
circleReg.Append(
.*?s[0-9]\\d*.createDateStr=\”(?<createDateStr>.*?)\”);
circleReg.Append(
.*?s[0-9]\\d*.creatorId=(?<creatorId>[0-9]\\d*[^;]));
circleReg.Append(
.*?s[0-9]\\d*.creatorName=\”(?<creatorName>.*?)\”);
circleReg.Append(
.*?s[0-9]\\d*.creatorSpaceUrl=\”(?<creatorSpaceUrl>.*?)\”);
circleReg.Append(
.*?s[0-9]\\d*.description=\”(?<description>.*?)\”);
circleReg.Append(
.*?s[0-9]\\d*.joinDeclaration=\”(?<joinDeclaration>.*?)\”);
circleReg.Append(
.*?s[0-9]\\d*.linkImgUrl=\”(?<linkImgUrl>.*?)\”);
circleReg.Append(
.*?s[0-9]\\d*.memberNum=(?<memberNum>[0-9]\\d*[^;]));
circleReg.Append(
.*?s[0-9]\\d*.name=\”(?<name>.*?)\”);
circleReg.Append(
.*?s[0-9]\\d*.urlName=\”(?<urlName>.*?)\”);
circleReg.Append( .*?s[0-9]\\d*.visitNum=(?<visitNum>[0-9]\\d*[^;]));


通过组装参数数据,然后获取页面数据,对页面数据进行分析即可,主要代码如下所示:

if (mc.Success)
{
string message = string.Format(正在处理类型{0}:{1}, 第{2}次数据, 共处理了{3}, urlDict[key], url, i + 1, j);
CallCtrlWithThreadSafety.SetText(
this.lblTips, message, this);
Application.DoEvents();
Thread.Sleep(
10);

MatchCollection mcs = re.Matches(content);
foreach (Match me in mcs)
{
#region MyRegion
j
++;

int memberNum = 0;
try
{
memberNum
= Convert.ToInt32(me.Groups[memberNum].Value);
}
catch { }
if (memberNum < 50)
{
flag
= false;
break;
}

sql
= string.Format(@”insert into Circle(circleId,circleType1Str,circleType2Str,createDateStr,creatorId,
creatorName,creatorSpaceUrl,description,joinDeclaration,linkImgUrl,memberNum,name2,urlName,SubTypeName)
values(‘{0}’,'{1}’,'{2}’,'{3}’,'{4}’,'{5}’,'{6}’,'{7}’,'{8}’,'{9}’,'{10}’,'{11}’,'{12}’,'{13}’)
, me.Groups[circleId].Value,
UnicodeHelper.UnicodeToString(me.Groups[
circleType1Str].Value.Replace(, “”)), UnicodeHelper.UnicodeToString(me.Groups[circleType2Str].Value.Replace(, “”)),
me.Groups[
createDateStr].Value, me.Groups[creatorId].Value, UnicodeHelper.UnicodeToString(me.Groups[creatorName].Value),
me.Groups[
creatorSpaceUrl].Value, UnicodeHelper.UnicodeToString(me.Groups[description].Value.Replace(, “”)), UnicodeHelper.UnicodeToString(me.Groups[joinDeclaration].Value.Replace(, “”)),
me.Groups[
linkImgUrl].Value, me.Groups[memberNum].Value, UnicodeHelper.UnicodeToString(me.Groups[name].Value.Replace(, “”)), me.Groups[urlName].Value, urlDict[key]);
command
= db.GetSqlStringCommand(sql);
try
{
db.ExecuteNonQuery(command);
}
catch (Exception ex)
{
LogTextHelper.WriteLine(sql);
LogTextHelper.WriteLine(ex.ToString());
}

message = string.Format(正在处理{0}:{1} 正在写入数据{2}次, urlDict[key], url, j);
CallCtrlWithThreadSafety.SetText(
this.lblTips, message, this);
Application.DoEvents();
Thread.Sleep(
10);

#endregion
}
}
else
{
flag
= false;//没有匹配就停止
break;
}

}

构造获取圈子用户信息也是比较复杂的一个过程,需要组装更多的参数来获取相关的数据,部分主要实现代码如下所示:

httpHelper = new HttpHelper();
httpHelper.Encoding
= Encoding.Default;
cookie
= new CookieContainer();
Regex re
= null;
Match mc
= null;
int pageSize = 30;
string url = http://q.163.com/dwr/call/plaincall/CircleBean.getNewCircleUsers.dwr;

foreach (string key in circlelDict.Keys)
{
string circleId = key;
string urlName = circlelDict[key];
string refUrl = string.Format(http://q.163.com/{0}/members/, urlName);

#region 内容正则表达式
StringBuilder circleReg
= new StringBuilder();
circleReg.Append(
s[0-9]\\d*.ageStr=\”(?<ageStr>.*?)\”);
circleReg.Append(
.*?s[0-9]\\d*.city=\”(?<city>.*?[^;])\”);
circleReg.Append(
.*?s[0-9]\\d*.hometownCity=(\”(?<hometownCity>.*?[^;])\”|(?<hometownCity>null)));
circleReg.Append(
.*?s[0-9]\\d*.hometownProvince=(\”(?<hometownProvince>.*?)\”|(?<hometownProvince>null)));
circleReg.Append(
.*?s[0-9]\\d*.name=(\”(?<name>.*?)\”|(?<name>null)));
circleReg.Append(
.*?s[0-9]\\d*.nickname=(\”(?<nickname>.*?)\”|(?<nickname>null)));
circleReg.Append(
.*?s[0-9]\\d*.profileImage140=\”(?<profileImage140>.*?)\”);
circleReg.Append(
.*?s[0-9]\\d*.profileImage60=\”(?<profileImage60>.*?)\”);
circleReg.Append(
.*?s[0-9]\\d*.province=\”(?<province>.*?)\”);
circleReg.Append(
.*?s[0-9]\\d*.qq=(\”(?<qq>.*?)\”|(?<qq>null)));
circleReg.Append(
.*?s[0-9]\\d*.realName=(\”(?<realName>.*?)\”|(?<realName>null)));
circleReg.Append(
.*?s[0-9]\\d*.spaceName=(\”(?<spaceName>.*?)\”|(?<spaceName>null)));
circleReg.Append(
.*?s[0-9]\\d*.userId=(?<userId>[0-9]\\d*[^;]));
circleReg.Append(
.*?s[0-9]\\d*.userName=\”(?<userName>.*?)\”);
#endregion

bool flag = true;
int i = 0;
int j = 0;
List
<CircleMemberInfo> entityList = new List<CircleMemberInfo>();
while (flag)
{
#region 构造提交参数
StringBuilder sb
= new StringBuilder();
sb.AppendFormat(
callCount=1);
sb.AppendFormat(
&page=/{0}/members/, urlName);
sb.AppendFormat(
&httpSessionId=);
sb.AppendFormat(
&scriptSessionId=D4DAC4AD9C3BF9B71C82802BDDBA0C25369);
sb.AppendFormat(
&c0-scriptName=CircleBean);
sb.AppendFormat(
&c0-methodName=getNewCircleUsers);
sb.AppendFormat(
&c0-id=0);//保留字符
sb.AppendFormat(&c0-param0=number:{0}, circleId);//11
sb.AppendFormat(&c0-param1=number:{0}, pageSize);//数量
sb.AppendFormat(&c0-param2=number:{0}, pageSize * i);//0,30,60
sb.AppendFormat(&c0-param3=boolean:true);
sb.AppendFormat(
&batchId={0}, i);

i++;

#endregion


然后我们通过代码来获取页面数据了,实现代码如下:

string content = “”;
try
{
httpHelper.ContentType
= text/plain;
content
= httpHelper.GetHtml(url, cookie, sb.ToString(), true, refUrl);
re
= new Regex(circleReg.ToString(), RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace);
mc
= re.Match(content);
}
catch (Exception ex)
{
LogTextHelper.WriteLine(ex.ToString());
break;

}


然后我们就开始用正则表达式来分析返回的数据,以便显示或者添加到数据库中,以供他用,代码实现如下所示:、

MatchCollection mcs = re.Matches(content);
foreach (Match me in mcs)
{
#region MyRegion
j
++;

sql = string.Format(@”insert into CircleMember(userId,userName,realName,nickname,circleId)
values(‘{0}’,'{1}’,'{2}’,'{3}’,'{4}’)
, me.Groups[userId].Value, httpHelper.RemoveHtml(UnicodeHelper.UnicodeToString(me.Groups[userName].Value)),
httpHelper.RemoveHtml(UnicodeHelper.UnicodeToString(me.Groups[
realName].Value.Replace(, “”))), httpHelper.RemoveHtml(UnicodeHelper.UnicodeToString(me.Groups[nickname].Value.Replace(, “”))), circleId);
command
= db.GetSqlStringCommand(sql);
try
{
db.ExecuteNonQuery(command);
}
catch (Exception ex)
{
LogTextHelper.WriteLine(sql);
LogTextHelper.WriteLine(ex.ToString());
}

message = string.Format(正在处理{0} 正在写入数据{1}次, urlName, j);
CallCtrlWithThreadSafety.SetText(
this.lblTips, message, this);
Application.DoEvents();
Thread.Sleep(
10);
#endregion

}


以上就是获取数据的一个完整的过程,其中涉及到获取圈子大类、圈子分类、圈子信息,以及最终获取圈子的用户信息,其中较为详细的介绍了各种数据的正则分析过程,如果您有这方面的应用,一个可以参考下面的代码,第二个也可以参考我的软件《易博搜搜》,其中就涉及到了网易博客圈子的邮件采集,如下所示。


该软件除了可以采集网易博客圈子用户的邮件信息,给营销推广人提供资料外,还可以利用网易博客的找朋友模块,获取相关的用户数据信息,当然也是可以转换为邮件地址信息的了,如下所示。

以上对网易博客的应用的代码实现以及一个较为综合的软件产品介绍,希望能带给大家更多的启示和知识了解。

[转载]黑客伪造Google Android更新,瞄准中国Android用户

mikel阅读(895)

[转载]黑客伪造Google Android更新,瞄准中国Android用户_IT新闻_博客园.

据安全公司赛门铁克(Symantec)报道,Google最新的Android操作系统系统更新似乎被黑客攻破了。

Google刚刚发布一个叫做“Android市场安全工具(Android Market Security Tool)” 的程序来杀死“DroidDream”Android手机病毒,赛门铁克发现的这个病毒软件也叫“Android市场安全工具”,只不过对Google的 程序进行了重新打包。赛门铁克称这个虚假安全工具会发送短信到一个指挥控制服务器。目前他们正在分析病毒代码,这个病毒是在一个第三方应用市场中发现的, 攻击对象是中国用户。

最令人震惊的是这个病毒的代码托管在Google Code 上,采用了Apache许可协议。该病毒表明黑客对Android很感兴趣。

上周Google罕见地强制用户在Android手机上安装了Android市场安全工具,以便除去DroidDream病毒。通常负责向设备 发布更新的都是手机厂商或电信运营商,Google很少自己发布更新。Google之所以这么做是因为Google官方Android应用市场中有50多 款应用感染了DroidDream病毒,该病毒可以盗取用户的IMEI、IMSI等信息,然后发送到一台位于加州Fremont的服务器上。

DroidDream还会下载其他代码到用户的手机上,利用“exploid”和“rageagainstthecage”两个漏洞来感染手 机。Google已经在Android 2.2.2以上版本中打上了补丁,但遗憾的是很多Android用户没有安装最新版Android。卡巴斯基病毒分析师称Google的这个工具并没有修 复遭到攻击的漏洞,只不过除去了DroidDream。