博文

目前显示的是 四月, 2012的博文

Howto:从C++对象指针得到类名

JAVA程序在运行的时候,有丰富的动态类型信息。而C++则困难的多。C++的运行时类型信息有3种实现方式:语言本身的RTTI、MFC的CObject、QT的moc。下面仅介绍前两种。 一、语言本身的RTTI: 如果是POD类型,如:class PodPoint{ public: int x; int y; }; 那么它和C语言中的struct没有什么区别。sizeof(PodPoint)=8。偏移值内容0x4y 别妄想能从它的对象指针中得到什么类型信息。 如果它有虚函数,那么就不一样了class PodPoint{ public: int x; int y; virtual ~PodPoint(){}; }; 在32位程序中,sizeof(PodPoint)=12。这是因为凡是有虚函数,就必须有vtable。所以PodPoint的实际布局就变成了这样:偏移值内容0指向vtable的指针4x8y如果编译的时候打开了RTTI(在vc2005及以上版本默认会打开),那么就很有意思了。在vtable[-1]的位置,是一个特殊的指针,指向RTTI Complete Object Locator,它的第12个字节开始,是一个指针,指向type_info对象。于是我就写了下面这样的代码:voidprintMyClassInfo(void *p){ type_info*** vtable=(type_info***)(*(int*)p); type_info** v1=vtable[-1]; type_info* v=v1[3]; printf("%s\n",v->name()); } 在有vtable的情况下,这个函数工作的非常好。 二、MFC的RTTI MFC中的大多数对象都从CObject继承而来,例如:class MyPoint:public CObject{ public: int x; int y; DECLARE_DYNAMIC(MyPoint) }; IMPLEMENT_DYNAMIC(MyPoint,CObject) 那么我们就可以通过调用CObject的virtual CRuntimeClass* GetRuntimeClass() …

Address Space Load Randomization以及如何禁用

图片
从Vista开始,Windows引入了一个新特性,叫Address Space Load Randomization(ASLR)。简单点说,就是将EXE/DLL的载入基址随机化。ASLR已经是一个非常普遍的特性,在几乎所有的现在操作系统中都引入了(如Linux、Windows Vista/7、iOS5)。但是ASLR对程序员来说可不是个好东西,明显增大了调试程序的难度。最近我在对Adobe Flash Player做逆向工程,发现我用ida启动调试的时候,经常会出现一个对话框,说"Rebasing program to xxxxx“。别听它说什么”Just a moment”,实际上要等很久很久才好。因为基址改变后,所有的地址都得重新计算,整个程序需要被重新分析一遍。用SysinternalsSuite中的Process Explorer(procxp.exe)可以查看一个进程是否启用了ASLR:通过修改PE文件的头部,可以禁用掉ASLR。强烈建议在对任何EXE/DLL做逆向工程前,先禁用掉它的ASLR选项,然后再往IDA/OllyDbg里面拖。下面用visual studio中自带的工具来查看并修改PE头:首先打开"Visual Studio 命令提示”,然后输入D:> dumpbin /headers flashplayer_11_sa_debug_32bit.exe就可以查看到这个PE文件的头部信息。输出很长,在OPTIONAL HEADER VALUES中有一项是”DLL characteristics“,如8140 DLL characteristics
Dynamic base
NX compatible
Terminal Server Aware如果它的值是8140,就说明打开了"Dynamic base”。用VC的链接器禁用掉它即可。D:> link /edit /dynamicbase:NO flashplayer_11_sa_debug_32bit.exe再 试一试吧!

联通iphone套餐对比

联通iphone套餐实在是让人眼花缭乱,到底选哪个好呢?本文的目的是为了给你拨开数字背后的秘密。如果我想买个iphone 4 8G,准备使用联通的网。那么现在有3种选择联通预存话费送手机联通购手机入网送话费在苹果的官网购机入网。我的思路是,首先分析我想要得到什么样的服务,然后计算我需要为之花多少钱。为了分析简单,下面假设我每月使用96套餐,并且打算使用2年左右,那么下面分析上述3个方案的总计支出方案1:联通预存话费送手机,合约价4999。选择96套餐,每月联通返91,所以我需要再付5块。总计支出4999+5*24=5119。方案2:裸机价格3999,每个月返38的话费,我需要再付(96-38)*24=1392元,总计支出3999+1392=5391。方案3:裸机价格3988。联通现在有1年期的入网送话费活动,一次存168,每月返28+14,带4的再加10块。总计支出:3988+(96-28-14-10)*24+168*2=5380,这里特别强调"带4的每月返10块"是因为,联通官网上剩下的号码都是些不怎么好的号码,一般都带4。有了上面的计算之后,下面介绍下我是怎么分析"预存话费送手机"这个表,还是以2年期为例:首先,购手机入网送话费不是针对Iphone特有的,这张表几乎对所有手机适用,而且联通和电信的这张表几乎完全一致。这意味着,如果联通如果要推出一个2年期的自购手机入网送话费活动,大致也是应该按照这张表返还。所以,我们要从"预存话费送手机"这张表中去除掉"购手机入网送话费"的影响。具体做法,首先从"购手机入网送话费"这个表中,找到对应的套餐,然后用"月送话费金额"*24,加到"预存话费送手机 "这张表的"优惠购机款"上,就是实际购机价格。6696126156优惠购机款3199279924992199月送话费金额26385062实际购机价3823371136003687经常有人说联通iphone的126套餐是鸡肋,这要看你怎么看了。从不同的角度分析,会得到不同的结果。不过这还没完。我们没算利息。以96套餐为例,假设年利率5%,那么方案1可得到4999*0.05*2+5*24*0.05=505.9元。方案2可…

DHPublicKey与byte[]转换的问题

背景:网络上经常采用Diffie-Hellman算法来交换密钥。通讯的双方首先共享2个公开数字:p和g。其中p是一个大质数,g通常等于2。则\( Z_p=\{a=g^n \pmod{p}, n \in N \} \) 构成一个整数群。密钥的生成方法:\(Z_p\)中选取一个随机数x,然后计算\( y=g^x \)。那么x,y构成一个keypair。x是私钥,y是公钥。那么每个人只需要把自己的公钥发出去,然后通信的时候选取一个对称加密算法,利用\(y^x\)作为通信的加密密钥即可。其中x是自己的私钥,y是对方的公钥。实际在用JAVA实现的时候:公钥和私钥可以通过java.security.KeyPairGenerator生成。//DH是算法名,SunJCE是Java Security API的Provider名,此处使用JDK自带的的SunJCE。 KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH","SunJCE"); 然后初始化KeyPairGenerator 这时需要传入一个java.security.spec.AlgorithmParameterSpec对象。kpg.initialize(MODP_GROUP2); MODP_GROUP2对象是这么来的:StringBuffer sb = new StringBuffer(); sb.append("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"); sb.append("29024E088A67CC74020BBEA63B139B22514A08798E3404DD"); sb.append("EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"); sb.append("E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"); sb.append("EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381"); sb.appe…

Birthday Problem and Hash Collision

1月份的时候,我们公司的数据部门给我们做了一次统计学的培训。 那天参加培训的大概有30-40人,主讲当时提了这样一个问题,在参加培训的人当中,有两个人是同月同日生的概率是多少? 答案是“大于70%”。这个答案令当场的很多人吃惊。于是现场做了一下实验,确实找到了两个生日相同的人。这个问题如果从数学角度来分析,可以看成这样:有m个球,和n个桶。依次将这m个球扔入这n个桶中的随机一个。最终,有一个桶内至少有两个球的概率是多少?解答:首先,我们拿起一个球,随便扔到一个桶里。然后拿起第二个球,也扔到一个桶里。那么第二个球和第一个球被扔进同一个桶里的概率是\( \frac{1}{n} \),不在同一个桶里的概率是\( 1- \frac{1}{n} \)。假设前两个球不在同一个桶里,那么我们继续,拿起第三个球扔下去,它和前两个球不在同一个桶里的概率是\( 1- \frac{2}{n} \)。即,对于第k个球来说,假如前面k-1个球都在不同的桶里,那么第k个球被扔到一个新桶中的概率就是\( 1- \frac{k-1}{n} \)。于是,最终有一个桶内至少有两个球的概率就是$$ P =1 - (1- \frac{1}{n})(1- \frac{2}{n})(1- \frac{3}{n}) \dots (1- \frac{m-1}{n}) $$下面尝试给出一个更简单的近似值:首先,高等数学课上学过一个很重要的式子:当x远远小于1时,有\(e^x \approx 1 + x \)。于是,当m远远小于n的时候:$$ (1- \frac{1}{n})(1- \frac{2}{n})(1- \frac{3}{n}) \dots (1- \frac{m-1}{n}) \approx \Pi_{j=1}^{m-1}e^{-\frac{j}{n}} = e^{-\sum_{j=1}^{m-1}{\frac{j}{n}}} = e ^ {-\frac{m(m-1)}{2n}} $$生日问题其实在计算机算法中经常遇到:假设一个Hash Table有n个桶,需要插入m个元素,那么插入过程中发生hash冲突的概率是多大? \( 1- e ^ {-\frac{m(m-1)}{2n}} \)另外,假如我希望发生hash冲突的概率小于0.5,那么n至少应该为多大?求解$$ 1- e ^ {-\frac{m(…