Python获取Chrome浏览器已保存的所有账号密码

昨天写了获取WIFI密码的脚本,今天继续写一段python脚本获取Chrome浏览器已保存的账号和密码。

Chrome浏览器已保存的密码都保存在一个sqlite3数据库文件中,和Cookies数据库在同一个文件夹,类似:

C:\Users\Lucas Lee\AppData\Local\Google\Chrome\User Data\Default\Login Data

使用CryptUnprotectData函数解密数据库中的密码字段,即可还原密码,只需要User权限,并且只能是User权限

为了防止出现读写出错,建议先把数据库临时拷贝到当前目录。

程序会读出所有的账号、密码、网站,写入文件夹下ChromePass.txt文件

代码如下:

import os, sys
import shutil
import sqlite3
import win32crypt

outFile_path = os.path.join(os.path.dirname(sys.executable),
                            'ChromePass.txt') 
if os.path.exists(outFile_path):
    os.remove(outFile_path)


db_file_path = os.path.join(os.environ['LOCALAPPDATA'],
                            r'Google\Chrome\User Data\Default\Login Data')
tmp_file = os.path.join(os.path.dirname(sys.executable), 'tmp_tmp_tmp')
if os.path.exists(tmp_file):
    os.remove(tmp_file)
shutil.copyfile(db_file_path, tmp_file)    # In case file locked
conn = sqlite3.connect(tmp_file)
for row in conn.execute('select username_value, password_value, signon_realm from logins'):
    pwdHash = str(row[1])
    try:
        ret =  win32crypt.CryptUnprotectData(pwdHash, None, None, None, 0)
    except:
        print 'Fail to decrypt chrome passwords'
        sys.exit(-1)
    with open(outFile_path, 'a+') as outFile:
        outFile.write('UserName: {0:<20} Password: {1:<20} Site: {2} \n\n'.format(
            row[0].encode('gbk'), ret[1].encode('gbk'), row[2].encode('gbk')) )
conn.close()
print 'All Chrome passwords saved to:\n' +  outFile_path
os.remove(tmp_file)    # Remove temp file

Windows可执行文件 (路径中不要有中文)
在Github获取

Python使用Chrome浏览器的Cookies发起HTTP请求

昨天我写了两篇博客,介绍:

1) 如何使用httplib带Cookies字符串发起请求

2) 如何解析Cookies字符串、创建CookieJar对象,自动管理Cookies的添加、更新、删除

本篇顺着介绍如何在Python中使用Chrome浏览器已有的Cookies发起HTTP请求。

Chrome的Cookies文件保存路径类似于:

C:\Users\Lucas Lee\AppData\Local\Google\Chrome\User Data\Default\Cookies

其中C:\Users\Lucas Lee\AppData可通过环境变量os.environ[‘LOCALAPPDATA’]获取。

Cookies是一个Sqlite3数据库文件。

了解完上述事实,问题就非常简单了:

从数据库中查询到所需的Cookies,更新到一个CookieJar对象中。再使用这个CookieJar创建opener即可。

函数build_opener_with_chrome_cookies展示了一个基本的实现,当省略domain时,会导入所有的Cookie,建议提供domain参数。

import os
import sqlite3
import cookielib
import Cookie
import urllib2

def build_opener_with_chrome_cookies(domain=None):
    cookie_file_path = os.path.join(os.environ['LOCALAPPDATA'], r'Google\Chrome\User Data\Default\Cookies')
    if not os.path.exists(cookie_file_path):
        raise Exception('Cookies file not exist!')
    conn = sqlite3.connect(cookie_file_path)
    sql = 'select host_key, name, value, path from cookies'
    if domain:
        sql += ' where host_key like "%{}%"'.format(domain)
        
    cookiejar = cookielib.CookieJar()    # No cookies stored yet

    for row in conn.execute(sql):
        cookie_item = cookielib.Cookie(
            version=0, name=row[1], value=row[2],
                     port=None, port_specified=None,
                     domain=row[0], domain_specified=None, domain_initial_dot=None,
                     path=row[3], path_specified=None,
                     secure=None,
                     expires=None,
                     discard=None,
                     comment=None,
                     comment_url=None,
                     rest=None,
                     rfc2109=False,
            )
        cookiejar.set_cookie(cookie_item)    # Apply each cookie_item to cookiejar
    conn.close()
    return urllib2.build_opener(urllib2.HTTPCookieProcessor(cookiejar))    # Return opener


if __name__ == '__main__':
    
    opener = build_opener_with_chrome_cookies(domain='192.168.1.253')
    html_doc = opener.open('http://192.168.1.253').read()
    import re
    print 'Title:', re.search('(.*?)', html_doc, re.IGNORECASE).group(1)

测试代码中,我在Chrome浏览器登陆了无线路由器,opener打开的页面同样显示处于已登陆状态。

WIFIpass – Python获取本机保存的所有WIFI密码(附源代码)

于2015-5-1修改了脚本,在 Windows 7 下测试通过。

昨晚临睡前写了一小段python脚本,用于获取PC上保存过 的所有WIFI密码。因为XP和Win7系统保存的位置不相同: XP在注册表,而Win7、Vista等在ProgramData文件夹 ,对XP的支持暂未添加。 简单描述一下这段脚本所做的工作:

1. 获取ProgramData\Microsoft\Wlansvc\Profiles\Interfaces文件夹

WIFI密码经加密后,保存在ProgramData\Microsoft\Wlansvc\Profiles\Interfaces文件夹下,每个SSID对应一个xml文件。直接找到ProgramData文件夹就可以了,显而易见的方式有两种:

  1. Win32 API SHGetFolderPath函数获取
  2. os.environ[‘PROGRAMDATA’]环境变量获取

使用API函数完成更好。

2. 使用CryptUnprotectData函数解密

找到所有xml文件中keyMaterial标签中的内容,调用函数CryptUnprotectData依次解密即可。

3. 获取System权限

这段代码需要SYSTEM权限才能运行成功,这跟我们常用的”管理员身份”还有一些区别。这里我通过psExec创建一个交互式shell完成“权限提升”

WIFIpass

Windows可执行文件(运行成功后会在程序目录下创建一个WIFIpass.txt,包含所有SSID和明文密码)

python源代码

Python使用Cookie字符串发起HTTP请求的几个方法(2)

前篇介绍了直接使用httplib发送Cookie,简洁直观。创建cookielib.CookieJar对象自动管理Cookie稍繁琐一些,但是一旦创建,可供urllib2创建opener,后续的所有cookie更新和过期删除都是自动处理的。

1. 解析Cookie Str,得到Cookie.SimpleCookie对象

我们得到的Request Header中,Cookie是这样的格式:

Cookie: key1=val1; key2=val2; key3=val3

第一步是解析它,得到Cookie.SimpleCookie对象。通过字符串构造即可: Cookie.SimpleCookie(cookie_str)

得到的是一个dict-like对象,它的每一个值都是一个Set-Cookie语句,上述例子解析后是:

from Cookie import SimpleCookie
>>> sc = SimpleCookie('key1=val1; key2=val2; key3=val3')
>>> for c,v in sc.items():
...     print c,v
...
key3 Set-Cookie: key3=val3
key2 Set-Cookie: key2=val2
key1 Set-Cookie: key1=val1

2. 用SimpleCookie创建cooklib.Cookie对象

上述SimpleCookie不能直接使用,因为一个完整的Cookie,还必须包括额外的字段,如:domain、path、expires等。第二步工作是创建cooklib.Cookie对象,直接将key, value传入cooklib.Cookie类的构造函数即可。

得到一系列cookielib.Cookie对象,便可以依次用它们来更新CookieJar了。

3. 完整的示例代码

import cookielib
import Cookie
import urllib2

def build_opener_with_cookie_str(cookie_str, domain, path='/'):
    simple_cookie = Cookie.SimpleCookie(cookie_str)    # Parse Cookie from str
    cookiejar = cookielib.CookieJar()    # No cookies stored yet

    for c in simple_cookie:
        cookie_item = cookielib.Cookie(
            version=0, name=c, value=str(simple_cookie[c].value),
                     port=None, port_specified=None,
                     domain=domain, domain_specified=None, domain_initial_dot=None,
                     path=path, path_specified=None,
                     secure=None,
                     expires=None,
                     discard=None,
                     comment=None,
                     comment_url=None,
                     rest=None,
                     rfc2109=False,
            )
        cookiejar.set_cookie(cookie_item)    # Apply each cookie_item to cookiejar
    return urllib2.build_opener(urllib2.HTTPCookieProcessor(cookiejar))    # Return opener


if __name__ == '__main__':
    cookie_str = 'tLargeScreenP=1; Authorization=Basic%20HereIsMySecret; subType=pcSub; TPLoginTimes=2'
    opener = build_opener_with_cookie_str(cookie_str, domain='192.168.1.253')
   
    html_doc = opener.open('http://192.168.1.253').read()
    import re
    print 'Open With Cookie:', re.search('(.*?)', html_doc, re.IGNORECASE).group(1)

    html_doc = urllib2.urlopen('http://192.168.1.253').read()
    print 'Open Without Cookie:', re.search('(.*?)', html_doc, re.IGNORECASE).group(1)

运行结果:

build-cookiejar-from-str

192.168.1.253是我房间的路由器,第一次使用带Cookie的Opener请求,第二次不带Cookie请求。

Python使用Cookie字符串发起HTTP请求的几个方法(1)

一般,我们HTTP抓包得到的Cookie位于Request Header中,格式如下:

Cookie: key1=val1; key2=val2; key3=val3

要使用该字符串发起HTTP请求,有几种方法:

  1. 使用httplib添加到headers中
  2. 使用cookielib创建CookieJar对象在urllib2中使用
  3. 使用requests模块

它们各有不足:

  1. httplib不会自动管理cookie(不会在后续的请求中自动添加、更新、删除过期)
  2. cookielib的处理过程稍复杂
  3. requests需要另安装

使用httplib直接添加cookie到header

如果不需要程序自己管理cookie,这个方法是极简单的。下面简单示例处理GET请求:

import httplib
import urlparse

def request(url, cookie=''):
    ret = urlparse.urlparse(url)    # Parse input URL
    if ret.scheme == 'http':
        conn = httplib.HTTPConnection(ret.netloc)
    elif ret.scheme == 'https':
        conn = httplib.HTTPSConnection(ret.netloc)
        
    url = ret.path
    if ret.query: url += '?' + ret.query
    if ret.fragment: url += '#' + ret.fragment
    if not url: url = '/'
    
    conn.request(method='GET', url=url , headers={'Cookie': cookie})
    return conn.getresponse()

if __name__ == '__main__':
    cookie_str = 'tLargeScreenP=1; Authorization=Basic%20HereIsMySecret; subType=pcSub; TPLoginTimes=2'
    url = 'http://192.168.1.253'
    html_doc = request(url, cookie_str).read()
    import re
    print 'With Auth:', re.search('(.*?)', html_doc, re.IGNORECASE).group(1)

    html_doc = request(url).read()
    print 'Without Auth:', re.search('(.*?)', html_doc, re.IGNORECASE).group(1)

request函数就是全部的内容,测试IP 192.168.1.253是我房间的无线路由器。第一次HTTP请求带Cookie,第二次不带Cookie,返回的标题不一样:

httplib-cookie

python获取路由器IP

之前测试某个路由器漏洞时,写了一小段python脚本查找路由器IP。

实际上可以认为是端口扫描,程序只是粗略地检查是否开放了80端口。

import socket
import threading

routers = []
lock = threading.Lock()

def search_routers(): 
    routers = []
    local_ips = socket.gethostbyname_ex(socket.gethostname())[2]    # get local IP
    all_threads = []
    for ip in local_ips:
        for i in range(1, 255):
            array = ip.split('.')
            array[3] = str(i)
            new_ip = '.'.join(array)
            t = threading.Thread(target=check_ip, args=(new_ip,) )
            t.start()
            all_threads.append(t)
    for t in all_threads:
        t.join()

def check_ip(new_ip):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(1)
    result = s.connect_ex((new_ip, 80))
    s.close()
    if result == 0:
        lock.acquire()
        print new_ip.ljust(15), ' port 80 is open'
        routers.append((new_ip, 80))
        lock.release()

print 'Searching for routers, please wait...'
search_routers()

timeout可以设置成1秒或2秒。local_ips是获取多块网卡上绑定的IP,比如我的IP地址是192.168.1.4和192.168.56.1。而代码所做的事情就是扫描 [192.168.1.1 ~ 192.168.1.254]  [192.168.56.1 ~ 192.168.56.254] 有哪些IP开放80端口。

在我的PC上运行结果:

get-router-ips

其中192.168.1.1和192.168.1.253是我的无线modem和无线路由器。