解决问题第一步:澄清问题之5WHY法寻找根本原因
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解决问题第一步:澄清问题之5WHY法寻找根本原因相关的知识,希望对你有一定的参考价值。
参考技术A 在分析本源问题的时候, 我们用5why也就是5个为什么分析法。它最初由日本丰田公司创始人丰田佐吉提出来的。因为一个问题可能会有表面原因和根本原因,如果当你发现一个问题,只是解决了表面的原因,那么问题还是会不断地暴露出来。
所以当遇到一个问题时,不是简单地通过解决表面的症状来解决问题,而是要针对这个问题不停追问原因:为什么会发生。
通过反复追问,找到根本原因,才能从源头上解决问题。
比如说,你的朋友现在在做销售,他和你说,我现在工作很不开心,想换工作。然后你和他说,好啊,我支持你换工作,可以尝试商务拓展工作啊,我给你推荐。然后转行做了商务拓展,他还是很不开心,告诉你他又想换另一份工作..
实际上,当朋友和你说他做销售不开心的时候,这只是一个表面的问题,解决它就是换工作,但是这个方法没有考虑根本问题,就是为什么做销售不开心。实际上,他是一个有点社交恐惧的人,非常不喜欢也不善于和别人进行社交,所以做销售的时候才会不开心,而商务拓展工作性质跟销售差不多,同样也需要大量与人的沟通,他自然也不会开心。
所以,当我们遇到问题的时候,不能只停留在表面的问题上,而是要深入挖掘,找到根本原因,才能真正解决问题。
在使用5Why分析法时, 我们会不断问为什么。那么, 要针对什么来问为什么呢?
可以从以下三个角度来考虑:
我们从这三个角度进行提问,来不断追问为什么,从而找到问题的本源。
具体用法给大家两个例子,第一个是分析丰田汽车公司机器停机的原因:第一个为什么:为什么机器停机了?因为机器超载,保险丝烧断了。第二个为什么:为什么机器会超载?因为轴承的润滑不足。第三个为什么:为什么轴承会润滑不足?因为润滑泵失灵了,第四个:为什么润滑泵会失灵?因为它的轮轴耗损了。第五个:为什么润滑泵的轮轴会耗损?因为杂质跑到里面去了。这个才是最根本的原因。
第二个就是刚才给大家讲到的你朋友做销售不开心的例子,还是一样的场景,你的朋友找到你,和你倾诉,说做销售不开心,想要换工作。你可以这样问他:第一个为什么:为什么做销售不开心?因为每天工作都很累。第二个为什么:为什么每天工作都会很累?因为需要一直和人沟通,第三个为什么:为什么一直和人沟通会让你很累?因为非常讨厌社交,讨厌与人沟通。第四个为什么:为什么讨厌社交?因为自己从小到大有点社交恐惧,而且沟通能力也比较弱,所以很少在社交场合收到他人的正反馈。
好了,在这个例子中,当问到第四个为什么的时候,就已经可以得到答案了,你的朋友做销售工作不开心,想换工作,根本原因是因为自己社交恐惧,并且沟通能力不强。那这个时候你所要做的,就不是给他介绍一份商务拓展的工作,而是需要看自己是否能帮助他提高沟通能力,或者建议他换一份不需要大量沟通的工作。
当然, 在用5why这个方法的时候, 我们不能太过僵硬, 要注意几点:
在寻找原因时,要做到绝对的客观,努力避开主观或自负的假设,建立在事实基础上,而不是猜测、推测或假设。
因为有时候,我们内心会预设一个答案,只是通过5个为什么来验证自己是对的,这种方式是不可取的,应该是基于事实,有相应的证据。
比如说,一个顾客在商场摔倒了,经理用5个为什么来分析:
第一个为什么:为什么顾客会摔倒?因为他走路不看路。
第二个为什么:为什么走路不看路?因为注意力不集中。
其实这个分析就是没有基于事实, 而是出于自己的主观偏见, 设定了一个结果, 就是“都是顾客的错", 只是在用5Why分析法在验证自己的偏见。按照这样的方式,得出的结论就是顾客摔倒是自己的原因,商场不需要任何措施,那么,有可能潜在风险问题就没有得到解决,后续还会有其他顾客摔倒。
虽然叫5个为什么,但实际使用时不限定只做5次为什么的探讨,有时可能只要3次,有时也许需要10次,关键在于必须找到,所有可解决的原因里面,那个最根本的原因。
注意有一个定语,是原因必须是可解决的,否则这个原因即便是最根本的,也对解决问题没有帮助。
比如你觉得自己人脉少,于是用5why分析法这样分析。
为什么人脉少:因为喜欢宅在家里。
为什么喜欢宅在家里:因为不喜欢跟人打交道。
为什么不喜欢跟人打交道:因为性格内向。
分析到性格时,它虽然是本质原因,但性格很难改变,因此要再往上追溯一层,把不喜欢跟人打交道作为可解决的原因里最根本的。那针对这一原因,可以尝试从自身改变,突破自己的舒适圈,让自己为了完成工作或人生目标,而多和人打交道,这样才能真正解决问题。
在寻找原因时,要找可控的原因,一般是基于组织内部的原因而不能去找不可控的原因(比如顾客的原因)。
比如研发出的新产品投诉率高,究其原因是顾客使用方法不当。但这不能作为根本原因,而要从组织内部去想,比如是不是说明书的内容不够详细,等等。总之,5个为什么的最终目的是为了解决问题,不要太僵化。
经过这3个步骤,我们澄清了理解的偏差,挖掘了对方内心真正的诉求,找到了问题的本源,那是不是就可以着手解决问题了呢?可能还没有。因为在现实生活当中,我们常常会同时面临很多的问题,这些问题都需要我们分配时间和精力去解决。在这样的情况下,筛选出哪些问题是值得被解决的,就变得很重要。
<<<圈外商科学习笔记
脱壳实践之寻找OEP——两次内存断点法
0x00 前言
对于加壳程序第一件事就是要找到OEP(oringinal Entry point),由于加壳的缘故,当PE文件载入OD或者其他调试软件时进入的的往往是壳程序的入口地址。所以要进行逆向分析第一步就必须找到PE程序的原始入口点。
0x01 壳的加载过程
壳和病毒在某些方面比较类似,都需要比原程序更早获得控制权。壳修改了原程序的的执行文件的组织结构,从而比原程序更早获得控制权,并且并不会影响原程序的正常运行。了解的壳的加载过程对于脱壳加壳异常重要。壳的加载过程如下:
1)保存入口参数
加壳程序初始化时保存各个寄存器的值,外壳执行完毕,再恢复各个寄存器内容,最后再跳到源程序的入口处执行。通常,用pushad/popad,pushfd/popfd指令来保存的和恢复现场环境。
2)获取壳自己所需的API函数
一般的壳输入表只有GetProAddress,GetMoudleHanle,LoadLibrary这几个API函数,甚至只有Kernel32.DLL以及GetProAddress。如果需要其他的API函数,可以通过LoadLibraryA(W)或者LoadLibraryExa(W)将DLL文件映像映射到调用进程的地址空间,函数返回的HINSTANCE值用于标识文件映像到虚拟内存地址。
LoadLibrary函数的原型如下:
HINSTANCE LoadLibrary{
LPCTSTR lpLibFileName //DLL文件名地址
}
返回值:成功时返回模块句柄,失败返回NULL。
当DLL文件已经被映射到调用进程的地址空间里,可以调用GetModuleHanleA(W)函数获得DLL模块的句柄,函数的地址原型如下:
HMODULE GetModuleHandle{
LPCTSTR lpModuleName //DLL文件地址
}
一旦模块被加载,线程就可以调用GetProcAddress函数获取输入函数地址。函数的原型如下:
FARPROC GetProcAddress{
HMODULE hModlue //DLL模块句柄
LPCSTR lpProName //函数名
}
这三个函数异常重要,对于程序加壳帮助很大。后面几篇将会详细介绍用法,这里暂且罗列出来。
3)解密原程序的各个区块的数据
壳出于保护原程序代码和数据的目的,一般都会加密原程序文件的各个区块,在程序时外壳将会对这些数据解密,以让程序能够正常运行。壳一般都是按区块加密的,那么在解密时也是按区块解密的,并且把解密的区块数据按照区块的定义放在合适的内存位置。
4)ITA的初始化
ITA填写,本来应该由PE加载器实现。但是由于加壳时,自己构造了一个输入表,并且让PE文件头输入表指针指向了自建的输入表。所以PE装载器就对自建的输入表进行填写。那么原来PE输入表只能由外壳程序来填写了。外壳所要做的就是将这个新输入表结构从头到尾扫描一遍,对每一个DLL引入的所有函数重新获取地址,并填写在ITA表中。
5)重定位处理
文件执行时将被映像到指定的内存地址中,这个初始地址称为基址。对于EXE文件,windows系统会尽量使用EXE问价所指定的内存地址,比如某EXE问价的基址为40000h,而运行时Windows系统提供给程序使用的基地址也是40000h。这种情况就不需要重定位了。对于DLL文件,windows没办法每一次提供DLL运行时提供相同的基址。对于这种情况,重定位是必须的。此时壳程序也需要提供PE文件的重定位功能。所以加壳DLL文件比加壳EXE文件多一个重定位表。
6)HOOK-API
程序文件中输入表的作用是让windows系统在程序运行时提供API的实际地址给程序使用。在程序的第一行代码执行前,windows系统就完成了这项工作。
壳程序一般都修改了原程序的输入表,然后自己模仿windows系统的工作来填充输入表的中相关数据。在填充过程中,外壳程序可填充HOOK-API的代码地址,这样就可间接的获取程序的控制权。
7)跳转到程序入口点(OEP)
经历过以上步骤后,外壳程序的功能就完成了,随后他会把控制权交给原程序,一般的壳这里会有一个明显的“分界线”。当然现在越来越多的加密壳将OEP一段代码搬到外壳的地址空间里,然后将这段代码清除掉。这种方式称为StolenBytes。这样,OEP与外壳就没有明显的分界线了,这增加了脱壳的难度。
0x02 利用两次内存断点法手动找到OEP
两次内存法的原理就是利用了壳加载过程第三步时需要对各个区段进行解密并将解密后的区段写入各个区段,完毕之后会跳转至原程序的OEP处。当然,如果我们能判断出壳何时跳转至OEP处最好,但是一般这并不容易。但是我们可以先对.data区块下断后再运行程序(因为区段.code比.data先解压,运行到这个断点时.code以及解密完成),随后再对.code(有的编译器是.text)段下断在运行,这样程序就会停在OEP处(因为解密完成后壳程序一定再次返回到OEP处,将控制权交给原程序)。这个方法就是两次内存法。
0x03 实例介绍两次断点法找OEP过程
1)将文件拖入od,alt+m进入内存模板,随后对.data区块按F2下断,如下图:
2)点击F9运行,此时程序停在了下来,如下图:
这里其实马上就要对.data区块进行解密读写操作了,此时再alt+m进入内存模块,对.text(这个就是.code区块,由于编译器不同,有的显示.text区块)区块下断。
3)点击F9运行,此时程序停止,如下图:
其实这里就是原程序的OEP地址了,由于od对PE文件进行了分析,所以显示如上图,我们可以右键,删除模块分析即可得到下图:
标红框的地方就是OEP地址了。
0x04 总结
两次内存断点法虽然简单,但是我们还是要弄清楚其中的原理。它其实就是利用壳加载过程需要对区段进行解密然后返回原程序OEP这一特性。
以上是关于解决问题第一步:澄清问题之5WHY法寻找根本原因的主要内容,如果未能解决你的问题,请参考以下文章