程序异常退出,日志输出不全

背景:日志输出没有调fflush实时flush到文件,程序异常崩溃,部分日志在缓存中无法写到文件中。

解决办法:注册异常信号处理函数,并在回调函数中调用exit()

exit()会把所有的缓存flushed

发表在 C/C++ | 标签为 | 留下评论

linux 定位段错误的一个方法

背景:程序出现段错误,没有core文件产生,日志没来得及写堆栈信息。

步骤1:使用dmesg查看系统运行信息。

cstaspee[10259]: segfault at 4 ip 00007fdb92acd1df sp 00007fd9c5e65d20 error 6 in libcsta_scm.so[7fdb92aba000+1c000]

发现在cstaspee在调用libcsta_scm.so动态库出现段错误。

步骤2:计算错误点在动态库的地址

7fdb92aba000为模块(libcsta_scm.so)载入地址,
00007fdb92acd1df为程序崩溃点ip指令地址,
相减   00007fdb92acd1df - 7fdb92aba000 = 131DF,
差值为错误点在动态库的地址。

步骤3:使用objdump命令反汇编 或 addr2line

objdump -d libcsta_scm.so > /tmp/xxx.txt

xxx.txt部分文件内容

00000000000130df <_Z30csta_scm_baseServiceEventSetupP13STRUCT_CM_MSGiii>:
   130df:    55                       push   %rbp
   130e0:    48 89 e5                 mov    %rsp,%rbp
   130e3:    48 83 ec 30              sub    $0x30,%rsp
   130e7:    48 89 7d e8              mov    %rdi,-0x18(%rbp)
   130eb:    89 75 e4                 mov    %esi,-0x1c(%rbp)
   130ee:    89 55 e0                 mov    %edx,-0x20(%rbp)
   130f1:    89 4d dc                 mov    %ecx,-0x24(%rbp)
   130f4:    c7 45 fc 00 00 00 00     movl   $0x0,-0x4(%rbp)
   130fb:    e9 16 02 00 00           jmpq   13316 <_Z30csta_scm_baseServiceEventSetupP13STRUCT_CM_MSGiii+0x237>
   13100:    48 8b 0d d1 8e 20 00     mov    0x208ed1(%rip),%rcx        # 21bfd8 <[email protected]@Base-0x428>
   13107:    8b 45 fc                 mov    -0x4(%rbp),%eax
   1310a:    48 63 d0                 movslq %eax,%rdx
   1310d:    8b 45 e4                 mov    -0x1c(%rbp),%eax
   13110:    48 63 f0                 movslq %eax,%rsi
   13113:    48 89 d0                 mov    %rdx,%rax
   13116:    48 c1 e0 03              shl    $0x3,%rax
   1311a:    48 01 d0                 add    %rdx,%rax
   1311d:    48 c1 e0 06              shl    $0x6,%rax
   13121:    48 69 d6 d8 39 28 00     imul   $0x2839d8,%rsi,%rdx
   13128:    48 01 d0                 add    %rdx,%rax
   1312b:    48 01 c8                 add    %rcx,%rax
   1312e:    48 05 c0 09 04 00        add    $0x409c0,%rax
   13134:    8b 40 04                 mov    0x4(%rax),%eax
   13137:    83 f8 01                 cmp    $0x1,%eax
   1313a:    0f 85 8e 00 00 00        jne    131ce <_Z30csta_scm_baseServiceEventSetupP13STRUCT_CM_MSGiii+0xef>
   13140:    8b 45 fc                 mov    -0x4(%rbp),%eax
   13143:    48 63 d0                 movslq %eax,%rdx
   13146:    48 89 d0                 mov    %rdx,%rax
   13149:    48 c1 e0 03              shl    $0x3,%rax
   1314d:    48 01 d0                 add    %rdx,%rax
   13150:    48 c1 e0 06              shl    $0x6,%rax
   13154:    8b 55 e4                 mov    -0x1c(%rbp),%edx
   13157:    48 63 d2                 movslq %edx,%rdx
   1315a:    48 69 d2 d8 39 28 00     imul   $0x2839d8,%rdx,%rdx
   13161:    48 01 d0                 add    %rdx,%rax
   13164:    48 8d 90 c0 09 04 00     lea    0x409c0(%rax),%rdx
   1316b:    48 8b 05 66 8e 20 00     mov    0x208e66(%rip),%rax        # 21bfd8 <[email protected]@Base-0x428>
   13172:    48 01 d0                 add    %rdx,%rax
   13175:    48 83 c0 0c              add    $0xc,%rax
   13179:    0f b6 00                 movzbl (%rax),%eax
   1317c:    84 c0                    test   %al,%al
   1317e:    74 4e                    je     131ce <_Z30csta_scm_baseServiceEventSetupP13STRUCT_CM_MSGiii+0xef>
   13180:    48 8b 0d 51 8e 20 00     mov    0x208e51(%rip),%rcx        # 21bfd8 <[email protected]@Base-0x428>
   13187:    8b 45 fc                 mov    -0x4(%rbp),%eax
   1318a:    48 63 d0                 movslq %eax,%rdx
   1318d:    8b 45 e4                 mov    -0x1c(%rbp),%eax
   13190:    48 63 f0                 movslq %eax,%rsi
   13193:    48 89 d0                 mov    %rdx,%rax
   13196:    48 c1 e0 03              shl    $0x3,%rax
   1319a:    48 01 d0                 add    %rdx,%rax
   1319d:    48 c1 e0 06              shl    $0x6,%rax
   131a1:    48 69 d6 d8 39 28 00     imul   $0x2839d8,%rsi,%rdx
   131a8:    48 01 d0                 add    %rdx,%rax
   131ab:    48 01 c8                 add    %rcx,%rax
   131ae:    48 05 00 0a 04 00        add    $0x40a00,%rax
   131b4:    0f b7 40 0c              movzwl 0xc(%rax),%eax
   131b8:    0f b7 c0                 movzwl %ax,%eax
   131bb:    89 c7                    mov    %eax,%edi
   131bd:    e8 8e 0d ff ff           callq  3f50 <[email protected]>
   131c2:    83 f8 01                 cmp    $0x1,%eax
   131c5:    75 07                    jne    131ce <_Z30csta_scm_baseServiceEventSetupP13STRUCT_CM_MSGiii+0xef>
   131c7:    b8 01 00 00 00           mov    $0x1,%eax
   131cc:    eb 05                    jmp    131d3 <_Z30csta_scm_baseServiceEventSetupP13STRUCT_CM_MSGiii+0xf4>
   131ce:    b8 00 00 00 00           mov    $0x0,%eax
   131d3:    84 c0                    test   %al,%al
   131d5:    0f 84 37 01 00 00        je     13312 <_Z30csta_scm_baseServiceEventSetupP13STRUCT_CM_MSGiii+0x233>
   131db:    48 8b 45 e8              mov    -0x18(%rbp),%rax
   131df:    c7 40 04 01 00 00 00     movl   $0x1,0x4(%rax)
   131e6:    48 8b 45 e8              mov    -0x18(%rbp),%rax
   131ea:    c7 80 08 01 00 00 00     movl   $0x0,0x108(%rax)

在xxx.txt文件中查找步骤2的地址131DF,
可以知道问题出在csta_scm_baseServiceEventSetup
(echo _Z30csta_scm_baseServiceEventSetupP13STRUCT_CM_MSGiii |   c++filt     )

或者直接使用addr2line命令查看错误出在哪个文件哪一行。

addr2line -e libcsta_scm.so 131df

总结

dmesg 查看崩溃的信息,计算崩溃地址。

objdump或addr2line 找出断点所在的文件及位置。

发表在 C/C++ | 标签为 , , , , | 留下评论

wordpress 502


1.问题

搬瓦工逐步淘汰OpenVZ,OpenVZ 不能续费,只能重新选购KVM。意味着自己的wordpress要迁移到新的VPS。https://bandwagonhost.com/

安装完lnmp,数据库恢复、wordpress相关文件copy到新虚机,nginx配置,DNS解析,可以顺利访问网站,但是登陆后台部分页面出现502。

2.定位

nginx/1.14.0、mysql/5.5.60、php/ 5.6.36版本都是和原来一致的,试了网上的一些方法后都不行。然后自己乖乖的定位。 通过dmesg命令或 查看/var/log/syslog,发现php-fpm在调用libssl.so.1.1时出现段错误。

迁移前后的系统存在着差异,迁移前用的ubuntu 16.04,迁移后ubuntu 18.04,libssl版本一个1.0一个1.1,存在这差异。

3.解决

最后的解决方案,重新安装lnmp环境,php版本选择PHP 7.0.30,运行正常。
PHP 7.0.30依然依赖libssl.so.1.1但不会像5.5.60那样出现段错误,502页面也不出现了。


4.总结

以后干脆搞搞整成docker image得了。

5.题外话

迁移的时候看了两眼access.log,发现有人弱口令爆破自己的网站,哈哈哈。这小破站也值得搞?就怕贼惦记啊。
正好一直找不到好的弱口令集合,打算整理一下,整个弱口令集。

发表在 wordpress | 标签为 , , , , , | 留下评论

linux join命令

服务器上起了一堆服务,刚来公司没多久还搞不清谁和谁交互,设计文档/架构文档,什么?没有!服务都是通过socket通讯的,为了可以分别部署在多台物理服务器上。于是乎想基于netstat命令统计一下交互关系,肉眼看太费劲,用awk搞了半天最后放弃了。

最后发现一个join命令,很好使,记录一下。

netstat -tp | awk '{ print $4$5,$7 }' |sort -k 1 > netstat1.txt
netstat -tp | awk '{ print $5$4,$7 }' |sort -k 1 > netstat2.txt
join -1 1 -2 1 netstat1.txt netstat2.txt | \
		cut -d" " -f2,3 | sed 's#[0-9/\.]##g' |sort -u

前两行命令把第4,5,7列输出到netstat1.txt和netstat2.txt里,不同的是Local Address(4列)和Foreign Address(5列),netstat1.txt和netstat2.txt里调换下位置,而且4,5列合并在一起了。如果netstat1.txt和netstat2.txt第一列相同说明两个程序在交互。

接下来解释join命令大显身手的时候了,像sql语句里的join一样, 命令join把文件结合在一起根据: -1 1指的是第一个文件的第一列,-2 1指的是第二个文件 的第一列。cut -d” ” -f2,3只取第2,3列,sed ‘s#[0-9/.]##g’删除pid和. ,sort -u排序去重。

这样就可以一目了然smserver在和谁交互、imlprocess在和谁交互。

发表在 shell | 标签为 , | 留下评论

sprintf 段错误

最近迁移代码测试功能的时候发现一个段错误,打印堆栈显示std::string析构时段错误。最后分析原因:sprintf造成字符数组内存溢出,踩内存,导致附近std::string对象被改修,析构时产生段错误。

原代码

if(response_code == 200)
{
	sprintf(temp,"HTTP请求成功[%s]", strResponce.c_str());
	dispPlayMsg("HTTP请求",index,temp,WEB_LOG);
	
	return TRUE;
}

strResponce为http的响应结果,平时的都是本公司的soap服务,返回
字节数都很少,测试时的服务返回长度超过temp长度,溢出,踩内存。

修改后

if(response_code == 200)
{
	//sprintf易造成越界,导致段错误
	snprintf(temp, sizeof(temp), "HTTP请求成功[%s]", strResponce.c_str());
	dispPlayMsg("HTTP请求",index,temp,WEB_LOG);

	return TRUE;
}

慎用sprintf,尽量使用snprintf。
原来工作中就遇到过sprintf造成的段错误。

发表在 C/C++ | 标签为 , | 留下评论

printf/sprintf/NULL 空指针问题

最近从windows到linux 迁移代码,遇到了一个sprintf参数空指针段错误。

很疑惑,按说项目这么久不该出现段错误。

1.代码

原代码(用到msxml)

sprintf(pItemData.szNodeText,"%s",(const char*)nodeptr->Gettext());

移植后的代码(用到libxml2)

xmlCharTemp = xmlNodeGetContent(xmlChildNode);

sprintf(pItemData.szNodeText,"%s", (const char*)xmlCharTemp);

xmlFree(xmlCharTemp);

用什么xml解析库并不关键,关键是sprintf的参数都有可能是空指针。

于是乎实验了一下,发现vc++6.0 和 g++编译器存在差异性。

 

 

Windows-vc++6.0-sprintf截图

 

 

Linux-g++sprintf-截图

2.G++为什么会出现这种情况?

输出汇编代码

g++ test.cpp -S -o test.S

 .file "test.cpp"
.section .rodata
.LC0:
.string "%s"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $32, %rsp
movq $0, -8(%rbp)
leaq -32(%rbp), %rax
movl $0, %edx
movl $.LC0, %esi
movq %rax, %rdi
movl $0, %eax
call sprintf
leaq -32(%rbp), %rax
movq %rax, %rdi
call puts
movq -8(%rbp), %rdx
leaq -32(%rbp), %rax
movq %rdx, %rsi
movq %rax, %rdi
call strcpy
leaq -32(%rbp), %rax
movq %rax, %rdi
call puts
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-28)"
.section .note.GNU-stack,"",@progbits


会发现两次调用sprintf,第一次调用的call sprintf,第二次调用的call strcpy。

3.printf也会存在类似的段错误

Windows-vc++6.0-printf截图

 

Linux-g++-printf-截图

 

g++汇编代码

.file "test2.cpp"
.section .rodata
.LC0:
.string "%s"
.LC1:
.string "%s \n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $32, %rsp
movl %edi, -20(%rbp)
movq %rsi, -32(%rbp)
movq $0, -8(%rbp)
movq -8(%rbp), %rax
movq %rax, %rsi
movl $.LC0, %edi
movl $0, %eax
call printf
movq -8(%rbp), %rax
movq %rax, %rsi
movl $.LC1, %edi
movl $0, %eax
call printf
movq -8(%rbp), %rax
movq %rax, %rdi
call puts
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-28)"
.section .note.GNU-stack,"",@progbits

会发现前两次调用的call printf,而第三次调用call puts。

 

4.总结

尽量不要期待编译器去做空指针的判断优化,因为大多数情况下你不知道编译器是怎么实现的,况且编译器间存在差距,自己保证参数的不为空指针。

 

最后代码无奈改成了这个样子。

sprintf(pItemData.szNodeText,"%s", xmlCharTemp!=NULL?(const char*)xmlCharTemp:"(null)");

参考:https://stackoverflow.com/questions/11589342/what-is-the-behavior-of-printing-null-with-printfs-s-specifier

发表在 C/C++ | 标签为 , , | 留下评论

编译链接“ undefined reference to ”

最近在移植一个项目,从windows移植到Linux,在解决掉编译前期问题后,在链接的时候碰到了各种的“ undefined reference to ”问题。

检查所依赖的.h文件是否 #include <>

首先检查所依赖的.h文件是否 #include“xxx.h”

链接时缺少了相关的目标文件(.o)或者库文件(.so)

造成这种情况的原因比较多:

忘记指定目标文件(.o);

忘记指定链接库(-L /xxx/yyy/  -lA);

遗漏指定链接库(B动态库依赖A动态库,链接忘记指定A动态库 -lA)

fun.h

#ifndef __FUN_H__
#define __FUN_H__

int fun();

#endif

fun.cpp

#include "fun.h"
int fun()
{
	return 0;
}

fun1.h

#ifndef __FUN1_H__
#define __FUN1_H__

int fun1();

#endif

fun1.cpp

#include "fun.h"

int fun1()
{
	return fun();
}

缺少链接库

[email protected]:~/test# g++ -fpic -shared fun.cpp -o libfun.so
[email protected]:~/test# g++ -fpic -shared fun1.cpp -o libfun1.so
[email protected]:~/test# g++ main.cpp -o main -L ./ -I ./ -lfun1
.//libfun1.so: undefined reference to `fun()'
collect2: error: ld returned 1 exit status

正确的编译

[email protected]:~/test# g++ -fpic -shared fun.cpp -o libfun.so
[email protected]:~/test# g++ -fpic -shared fun1.cpp -o libfun1.so
[email protected]:~/test# g++ main.cpp -o main -L ./ -I ./ -lfun1 -lfun
[email protected]:~/test#

继续阅读

发表在 编译 | 标签为 , , | 留下评论

网络摄像头 弱口令扫描

确定想扫描的IP范围

首先要确定要扫描的ip范围,可以自己定手写,我是按地域从网站上爬取的。

#coding:utf-8
import requests
from bs4 import BeautifulSoup
from urllib import quote
import re
place_name = "日本"
url_ = 'http://ip.yqie.com/search.aspx?searchword=' + quote(place_name) + "&pagecurrent="
pagecount = re.findall('页码:1/(\d*?)<',requests.get(url_+'1').content)
index = 1
fp = open('ip_range.txt','a')
while index < int(pagecount[0]):
    url = url_ + str(index)
    page = requests.get(url)
    soup = BeautifulSoup(page.content,'lxml').find_all("tr")
    j = 0
    for i in soup:
        if j == 0:
            j = 1
            continue
        fp.write(i.contents[1].contents[0]  + '    ' + i.contents[3].contents[0] + '\n')
    index = index + 1
fp.close()

生成以下格式的文本:
171.105.32.0 171.105.33.255
171.105.34.0 171.105.35.255
171.105.36.0 171.105.36.255
171.105.37.0 171.105.38.255
171.105.39.0 171.105.79.255

继续阅读

发表在 杂项 | 标签为 , , | 留下评论

wordpress 恶意访问

在vps上抓包分析telegram协议时,意外发现有人尝试登录我的wordpress后台,很是意外,看来安全意识不能没有啊。

然后我装了个wordpress插件simple login log来记录登录日志,实验发现并不能记录登录失败的日志,所以看了下simple login log插件源码,simple-login-log.php文件中有以下代码行,

if( isset($this->opt['failed_attempts']) )

因为对php语言不是很了解,也没太仔细看opt在哪初始化或者修改的,索性直接把以上代码全替换成

if( 1 )

估计simple login log作者这么做是怕有攻击者对你网站实施密码爆破,使得mysql数据库爆掉。

而后就能看到登录失败的日志了。

仔细观察一下时间,你会发现这些人还蛮专业,隔两个小时尝试一次,怕短时间内多次访问被禁掉。

有一些插件可以做一些防护,比如:WP Limit Login Attempts、WP-Ban等,但考虑到本来vps内存cpu呀就不够用的,我就没安装这些插件了黑客还是蛮多的,不过我这小站也没啥,任他们去吧

 

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

Android QQ/微信 数据库

QQ和微信数据本地数据库,可以获取聊天信息以及好友信息等。

QQ

安卓手机QQ数据库:/data/data/com.tencent.qq/databases/QQ号.db(手机root后可获取 RE浏览器);
数据库文件为sqlite数据库;
私聊天记录放在表:mr_friend_MD5(QQ号)_New
群聊天记录放在表:mr_troop_MD5(群号)_New

sqlcipher.exe打开数据库发现一些信息乱码,经过加密。加密方法循环异或IMEI号。

解密demo:

# -*- coding: utf-8 -*-
import sqlite3

IMEI="866536022175869"
conn = sqlite3.connect("971774262.db")
cursor = conn.execute("SELECT frienduin,selfuin,senderuin,msgdata  from mr_troop_158C59D128304F55302B275E6427CA1E_New ")
print "select database successfully";
print "群号\t\t己方QQ\t\t发送方QQ\t\t聊天内容"
for row in cursor:
    a= row[0]
    #print a
    sbstr=""
    for i in range(0,len(a)):
        sbstr+=chr(ord(a[i])^ord(IMEI[i%15]))
    sbstr+="\t"
    a= row[1]
    for i in range(0,len(a)):
        sbstr+=chr(ord(a[i])^ord(IMEI[i%15]))
    sbstr+="\t"
    a= row[2]
    for i in range(0,len(a)):
        sbstr+=chr(ord(a[i])^ord(IMEI[i%15]))
    sbstr+="\t"
    a= row[3]
    for i in range(0,len(a)):
        sbstr+=chr(ord(a[i])^ord(IMEI[i%15]))
    print sbstr

微信

安卓微信数据库:/data/data/com.tencent.mm/MicroMsg    EnMicroMsg.db (需要ROOT)

数据库整个加密,可以用sqlcipher.exe软件直接打开,也可以自己写代码。

数据库密码:拼接IMEI和uin,通过md5加密后,取前7位小写的字符串

uin获取:/data/data/com.tencent.mm/shared_prefs/auth_info_key_prefs.xml (需要ROOT)

发表在 杂项 | 标签为 , | 留下评论