晕,我的韩国代理不能用了。

222.122.249.5:8080

非常快非常好的代理,如今挂了。不能连了。

google了一把这个IP,一堆的记录啊天啦。

不过现在终于倒了。

也好,搜这个IP能找到很多不错的代理网站。

用代理这个关键字反而找不到这么好的。呵呵,让SEO见鬼去吧。

发表在 日经 | 留下评论

windows 注册表的初始化

看了看wrk的代码,发现一个函数会调用ZwCreateFile打开注册表的文件,这个函数就是CmpOpenHiveFiles

这个函数会打开两个注册表文件,master为不带后辍的,secondary为带后辍的。

system32\config\system和software就是这样被加载的。

 

查找过程,先找SAM,这个词不常见,grep一下找到一个配置表:

 
HIVE_LIST_ENTRY CmpMachineHiveList[] = {
    { L"HARDWARE", L"MACHINE\\", NULL, HIVE_VOLATILE    , 0                         ,   NULL,   FALSE,  FALSE,  FALSE},
    { L"SECURITY", L"MACHINE\\", NULL, 0                , 0                         ,   NULL,   FALSE,  FALSE,  FALSE},
    { L"SOFTWARE", L"MACHINE\\", NULL, 0                , 0                         ,   NULL,   FALSE,  FALSE,  FALSE},
    { L"SYSTEM",   L"MACHINE\\", NULL, 0                , 0                         ,   NULL,   FALSE,  FALSE,  FALSE},
    { L"DEFAULT",  L"USER\\.DEFAULT", NULL, 0           , CM_CMHIVE_FLAG_UNTRUSTED  ,   NULL,   FALSE,  FALSE,  FALSE},
    { L"SAM",      L"MACHINE\\", NULL, HIVE_NOLAZYFLUSH , 0                         ,   NULL,   FALSE,  FALSE,  FALSE},
    { NULL,        NULL,         0, 0                   , 0                         ,   NULL,   FALSE,  FALSE,  FALSE}
    };

注册表应该就是从这里初始化的了。

再找引用:

 
    for (i = 0; i < CM_NUMBER_OF_MACHINE_HIVES; i++) {
        ASSERT( CmpMachineHiveList[i].Name != NULL );
        //  
        // just spawn the Threads to load the hives in parallel
        //  
        Status = PsCreateSystemThread(
            &Thread,
            THREAD_ALL_ACCESS,
            NULL,
            0,  
            NULL,
            CmpLoadHiveThread,
            (PVOID)(ULONG_PTR)(ULONG)i
            );  
 
        if (NT_SUCCESS(Status)) {
            ZwClose(Thread);
        } else {
            //  
            // cannot spawn thread; Fatal error
            //  
            CM_BUGCHECK(BAD_SYSTEM_CONFIG_INFO,BAD_HIVE_LIST,3,i,Status);
        }   
    }   

这里为每个hive创建一个线程,进入CmpLoadHiveThread函数:

  

 
 
// <sysroot>\config\hive
    if (CmpMachineHiveList[i].CmHive == NULL) {
 
        //
        // Hive has not been initialized in any way.
        //
 
        CmpMachineHiveList[i].Allocate = TRUE;
        Status = CmpInitHiveFromFile(&FileName,
                                     CmpMachineHiveList[i].HHiveFlags,
                                     &CmHive,
                                     &(CmpMachineHiveList[i].Allocate),
                                     CM_CHECK_REGISTRY_CHECK_CLEAN
                                     );
 
        if ( (!NT_SUCCESS(Status)) ||
             (!CmpShareSystemHives && (CmHive->FileHandles[HFILE_TYPE_LOG] == NULL)) )
        {
            ErrorParameters = &FileName;
            ExRaiseHardError(
                STATUS_CANNOT_LOAD_REGISTRY_FILE,
                1,
                1,
                (PULONG_PTR)&ErrorParameters,
                OptionOk,
                &ErrorResponse
                );
 
        }
 
 

CmpInitHiveFromFile会调用CmpOpenHiveFiles,后者会调用zwcreatefile打开相应的注册表文件。

如果要保护注册表,在创建线程前处理一下就好了。还只是猜想,哪天闲出毛病了再试试。

 

发表在 开发 | 标签为 | 留下评论

绕过dbghelp手动获取unloaded module(dll)信息

dbghelp有个功能,那就是MiniDumpWithUnloadedModules,
当os维护了已经unload的dll的列表时,它会在minidump文件中存入unloaded modules的信息。
只可惜的是,msdn中明说了,dbghelp 5.1并不支持这个标志。
看了一下winxpsp2自带的dbghelp.dll,恰好是这个版本的。

这一个标志是很重要的,因为某些BUG,经查恰好运行到一个非法的地址时Crash,
而这个非法的地址怎么看都像是原来有一个dll恰好加载在这里,但如今
这个dll已经被FreeLibrary了。如果有了这个unload modules的信息,
那么这个BUG就很容易找出来。如果没有的话,就麻烦了,因为程序代码
中都是com指针,虚表调来调处的根本不知道调用处正常情况应当调用的是哪个dll。
既然这个标志重要,自然应当把它启用,但winxp sp2恰恰不支持,如果为了这一个功能
就打包一个体积不小的dbghelp.dll的话,也划不来。

因此,想到一点:
何不自己把unloaded modules的信息,记载下来跟.dmp文件一起上报呢?

如是开始研究,先写了一个很小的程序来实现产生minidump的功能,然后用ollydbg来调试,
看dbghelp.dll是如何拿到unloaded modules的信息的。
程序虽小,五脏俱全,代码如下:

 
int Filter(_EXCEPTION_POINTERS * source, _EXCEPTION_POINTERS * dest)
{
 *dest->ContextRecord = *source->ContextRecord;
 *dest->ExceptionRecord = *source->ExceptionRecord;
 return EXCEPTION_EXECUTE_HANDLER;
}
 
void Doxx(EXCEPTION_POINTERS * p)
{
 HANDLE ho = CreateFile(L"oo.dmp", GENERIC_ALL, 0, NULL, CREATE_ALWAYS, 0, 0);
 
 _MINIDUMP_EXCEPTION_INFORMATION ExInfo;
 ExInfo.ThreadId          = GetCurrentThreadId();
 ExInfo.ExceptionPointers = p;
 ExInfo.ClientPointers    = TRUE;
 
 MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), ho, MiniDumpWithUnloadedModules, &ExInfo, 0, 0);
}
int main()
{
 EXCEPTION_RECORD ExceptionRecord;
 CONTEXT ContextRecord;
 EXCEPTION_POINTERS ptr;
 ptr.ExceptionRecord = &ExceptionRecord;
 ptr.ContextRecord = &ContextRecord;
 __try
 {
  *(int*)0 = 0;
 }
 __except (Filter(GetExceptionInformation(), &ptr))
 {
  Doxx(&ptr);
 }
}

然后反复查找应用的断点,找字符串找到:
GenGetProcessInfo.EnumUnloadedModules(0x%x) failed, 0x%08x
就从它入手了,找到相应的代码引用,然后看上下文,不多久找到了
NtWin32LiveSystemProvider::EnumUnloadedModules 函数,
一看实现,是从已经有的内存里copy一个字符串出来而已。
那还要找到这段内存如何来的,在指定改写处下硬点断点重跑,
发现这个内存是用ReadProcessMemory读来的,读的地址是7C99D8C0,
跑到那里一看,果然有unloaded 的 shimengine.dll的信息。
看了下od的log确认这个dll在exe的入口点之前被卸载。

接下来就查这个7C99D8C0是哪里来的了,往上翻代码,发现是调了一个函数,
在那里下断点重跑,找到了:

030656DE  |. FFD0    CALL EAX   ;  ntdll.RtlGetUnloadEventTrace

google一把RtlGetUnloadEventTrace,发现msdn2上居然有详细说明。
到是出乎意料。

OK,大功告成,总结如下:

windows xp sp2和2003 sp1以后,ntdll维护了unloaded module的信息。
由ntdll写入一个叫RtlpUnloadEventTrace的数组,并导出函数
RtlGetUnloadEventTrace返回该数组。代码实现:

#define RTL_UNLOAD_EVENT_TRACE_NUMBER 64
 
typedef struct _RTL_UNLOAD_EVENT_TRACE {
    PVOID BaseAddress;   // Base address of dll
    SIZE_T SizeOfImage;  // Size of image
    ULONG Sequence;      // Sequence number for this event
    ULONG TimeDateStamp; // Time and date of image
    ULONG CheckSum;      // Image checksum
    WCHAR ImageName[32]; // Image name
} RTL_UNLOAD_EVENT_TRACE, *PRTL_UNLOAD_EVENT_TRACE;
 
RTL_UNLOAD_EVENT_TRACE RtlpUnloadEventTrace[RTL_UNLOAD_EVENT_TRACE_NUMBER];
PRTL_UNLOAD_EVENT_TRACE RtlGetUnloadEventTrace()
{
    return RtlpUnloadEventTrace;
}

我们只需要调用RtlGetUnloadEventTrace即可拿到指向数组首元素的指针。
但是这个数组有多少项呢?msdn2上说是有64项,但dbghelp只读了16个,为什么呢?
如果64个,占用内存大小应当是:
sizeof(RTL_UNLOAD_EVENT_TRACE) * 64 = 54h*40h = 1500h
打开ntdll.dll的data segment一看,其实大小并没有这么多,只有540h个字节,
也就是说,至少在windows xp sp2,这个结构的大小只有10h即16个元素。
也许在其它版本如vista更大了吧,不管它。

到这里,要做的,无非就是GetProcAddress拿到RtlGetUnloadEventTrace,
拿到返回的指针,再读出16个结构出来,然后整理成我需要的报告形式,与
.dmp一起上报就好了。

发表在 开发 | 留下评论

百度知道的审核还是挺快的啊

试着在词条大意失荆州那里修改了几个错字,也不知道原来的人咋了,周瑜鲁肃等都能打错,中午改的,下行一看已经通过审核了,几个小时的时间,看来百度请了不少的劳力来做这种事啊。

发表在 日经 | 留下评论

惊闻TLF高层变动

TLF,多好的地方啊,0day随便下,注册会员速度比普通会员还快,
今天在水木上惊闻基高层变动,有人带人马出走,创建人退出。
也许今后不再有匿名的地方可以下到0day了,对中国网虫来说损失好大。
其实,它可以免费注册下载0day的模式,又不粘惹商业,这种靠热情维持的模式也许上天早就注定走不长远。但我更希望看到它粘点商业,不要太大,至少能让管理员有理由做下去就好了。

anyway, 等着这场戏演下去。

发表在 日经 | 一条评论

郁闷,hostmonster变慢了

原来ping值200ms多一点,这几天变成500多ms了。
真是不爽。试了一下godaddy,ping值在200多ms,唉,早知这样就申请godaddy的了。

C:\>ping godaddy.com
 
Pinging godaddy.com [208.109.132.201] with 32 bytes of data:
 
Reply from 208.109.132.201: bytes=32 time=268ms TTL=107
Reply from 208.109.132.201: bytes=32 time=214ms TTL=107
Reply from 208.109.132.201: bytes=32 time=217ms TTL=107
Reply from 208.109.132.201: bytes=32 time=218ms TTL=107
 
Ping statistics for 208.109.132.201:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 214ms, Maximum = 268ms, Average = 229ms
 
C:\>ping hostmonster.com
 
Pinging hostmonster.com [74.220.195.150] with 32 bytes of data:
 
Reply from 74.220.195.150: bytes=32 time=529ms TTL=41
Reply from 74.220.195.150: bytes=32 time=531ms TTL=41
Request timed out.
Reply from 74.220.195.150: bytes=32 time=525ms TTL=41
 
Ping statistics for 74.220.195.150:
    Packets: Sent = 4, Received = 3, Lost = 1 (25% loss),
Approximate round trip times in milli-seconds:
    Minimum = 525ms, Maximum = 531ms, Average = 528ms
发表在 未分类 | 郁闷,hostmonster变慢了已关闭评论

把activex控件标为安全的

to mark activex control dlls as safety

其实也是老生常谈的问题了,很简单但是要用到的时候却不一定记得。无非就是实现一下IObjectSafety接口。
接口名字我今天就忘了,查了好几下才查到。
这个接口只有两个函数,实现可如下:

STDMETHODIMP GetInterfaceSafetyOptions( REFIID riid, DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions )
{
 DWORD dwFlags = INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA;
 if (pdwSupportedOptions) *pdwSupportedOptions = dwFlags;
 if (pdwEnabledOptions) *pdwEnabledOptions = dwFlags;
 return S_OK;
}
STDMETHODIMP SetInterfaceSafetyOptions(REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions)
{
 return S_OK;
}
发表在 开发 | 留下评论

女孩子的心思

有个高中的同学跑来深圳出差,于是一伙老同学去吃了一顿。一位女生来点菜。

不久菜上来了,几位哥们刚各吃上一口,那女生突然开口了:你们怎么没有反应?

我们愣了,你期待什么反应?

回曰:“我点的菜你们怎么不说好吃?”

是啊,这菜确实还可以,但大家却是都忘了要赞美一下这个菜,当然赞美菜的实质是赞美人家点菜好。

女孩子的心想就是不同,其实并不复杂,但是你却想不到。

于是我只好回了一句:这又不是你做的,等下回吃你做的菜再赞美吧。

 

发表在 随笔 | 留下评论

刚才google搜了一把swigger这个词

发现居然是一个英国男装品牌,我以前还真不知道。ft,丫还把swigger.net留给我来注册?还有那个swigger.cn,页面搭得还马马虎虎嘛,但是没钱买英文国际域名?

丫会不会来找我要ID呢?要是找我来要就好了,呵呵。

发表在 日经 | 留下评论

支付宝为什么慢

说说前面文章提到的为什么支付宝慢的原因吧。

起因:买域名需要用支付宝付款,但支付过程实在是太慢了。

其实支付宝慢我几个月前就发现了,只是那一次还可以用财富通付款,所以我就选财富通了。这次只有淘宝可以选了,没办法只有用它付。

首先是尝试等,等了几下出了几次错,都是超时。不能再等了,转钱是件重要的事,如果因为某个步骤超时导致事情办不了,钱又被扣了,就麻烦了。

没办法,研究一下为什么慢吧。

1. 首先是要找出一个慢的场景,这要才可以作下一步的分析,

我试了两下,整出一个场景来,就是访问这个URL很慢:

http://bankacknowledge.alipay.com/payment/e_bank_payment.htm

 刷新了数次,大部分慢,只有一两次快。(注:发现这个慢是本blog域名买之前的事,写本文时访问了此url几次,发现挺快的了,也许是跟时间有关系)

怀疑是IE问题,换ff上,这个页面全打开也是很慢。跟IE一样,刷新多次一两次快,其余慢。

慢的时候,状态栏显示正在等待 img.alipay.com

分析了一下页面结构,要访问多个img.alipay.com上的  url如:

https://img.alipay.com/css/global/v2.0.css
https://img.alipay.com/pimg/icon_fold_3.gif

 

2. 然后当然是google之,关键词: 淘宝 支付 慢,最后在yahoo找到一篇:

http://ks.cn.yahoo.com/question/1390100028924.html

这里面提到了一件很重要的事,就是img.alipay.com。说要在host里指定一下IP。难道是这个站太慢?不至于马云这样的大财主不做IDC优化吧。

我试着ping 了一下:

 C:\>ping img.alipay.com

Pinging img.alipay.com [121.0.26.16] with 32 bytes of data:

Reply from 121.0.26.16: bytes=32 time=35ms TTL=246
Reply from 121.0.26.16: bytes=32 time=34ms TTL=246
Reply from 121.0.26.16: bytes=32 time=35ms TTL=246
Reply from 121.0.26.16: bytes=32 time=35ms TTL=246

Ping statistics for 121.0.26.16:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 34ms, Maximum = 35ms, Average = 34ms

应该说,速度挺快。又telnet img.alipay.com 443试了一下,立马连上,几次都如此,怀疑不是它的问题。

3. 尝试用wget 取url https://img.alipay.com/pimg/icon_fold_3.gif 查时间。发现手头的wget.exe版本太老,不支持https。

懒得去开linux了,更没时间去找新版的wget.exe了。手头有一个以前练手写的sget.exe,就拿它来试吧。

C:\>sget https://img.alipay.com/pimg/icon_fold_3.gif aa.gif
OK
HTTP code: 200
Date: Sat, 05 Apr 2008 17:28:57 GMT
Server: Apache
Last-Modified: Wed, 16 Jan 2008 14:17:01 GMT
ETag: “1f014c-271-90127140”
Accept-Ranges: bytes
Content-Length: 625
Cache-Control: max-age=604800
Expires: Sat, 12 Apr 2008 17:28:57 GMT
Keep-Alive: timeout=50, max=264
Connection: Keep-Alive
Content-Type: image/gif

还挺快的啊,一下就出来结果了,又运行一次,这次出情况了,一直没有出结果,卡住了,为什么呢?

打开VC编译一把源码开始调试,发现连接函数处:

  if (connect(sock, name, namelen) == 0 &&
   SSL_set_fd(ssl, (int)sock) &&
   SSL_connect(ssl) > 0)
  {
   return true;
  }

SSL_connect函数一直没有返回,这下问题就找到了:

img.alipay.com要么是压力大了承受不了了,要么是有潜在的BUG,在ssl握手时会出现问题,

导致客户端一直要等。导致淘宝ping起来很快,但某些页面访问起来很慢。

而tcp连接还是很快,所以我之前telnet img.alipay.com 443不能发现问题。

 

4. 原因查明了,方案就容易做了。先看了一下img.alipay.com要拉什么东西,其中.js和.css比较重要,图片就算了。

反复连接img.alipay.com,因为有一定机率很快连接成功,所以可以把它们都下载回来。

下回来后按目录结构放在本地一个文件夹里面。然后配置一下host:

127.0.0.1 img.alipay.com

再配了一下本地的apache,在这个文件夹启用hostname为img.alipay.com的https访问。

尝试访问一下本地的 https://img.alipay.com/css/global/v2.0.css

发现可以成功,唯独变的就是img.alipay.com是127.0.0.1了,还有就是ie会给一个证书错误的警告,选继续就好了。

然后重新刷了下 http://bankacknowledge.alipay.com/payment/e_bank_payment.htm

虽然有几个图不能显示,但是挺快的了。这样可以开始付款了。

打开淘宝付款流程,除了一些图片没有,一切正常,很快就成功打开招行专业版付了款。

搞定收功。可以买下域名了。

 

后记: 付款是大事,我敢这么做是因为我知道img.alipay.com不会影响付款逻辑。看官们谨慎点,最安全的办法还是等几个小时等到半夜好点。比如现在img.alipay.com就很快。

另外,yahoo上的回答说明已经有人知道这件事情了,虽然那里没有详细说明技术原因。yahoo现在也是马云管,马云应该也知道了,为什么就不做好一下img.alipay.com呢?

最后,像图片这样的东西完全没有必要通过https拉嘛,用http就行了,我知道alipay是为了照顾ie用户,因为混合https和http在一个页面内,IE会给出一个安全警告。

但是,既然你的img.alipay.com都承受不了压力了,这些图片css什么的,为什么就不直接从http拉呢?ie给个警告总比用户付不了款,等几次都超时出问题强吧。

发表在 老当益愤 | 标签为 , , , | 留下评论