运用DeepState对API举行隐约测试 | 申博官网
登录
  • 欢迎进入申博官网!
  • 如果您觉得申博官网对你有帮助,那么赶紧使用Ctrl+D 收藏申博官网并分享出去吧
  • 这里是申博官方网!
  • 申博官网是菲律宾sunbet官网品牌平台!
  • 申博开户专业品牌平台!

运用DeepState对API举行隐约测试

申博_新闻事件 申博 710次浏览 已收录 0个评论

新型Android木马Gustuff已影响上百家银行应用程序

近日,Group-IB的安全专家检测到了一种名为Gustuff的移动Android木马的攻击活动,其目标涵盖了国际知名银行的潜在客户、使用加密货币服务的用户,以及一些热门的电子商务网站。 Gustuff是一种新型的Android银行木马,之前从未被报道过。

DeepState是一个框架,它为C和c++开发人员供应了一个大众接口,用于种种符号实行和隐约引擎。用户可以或许运用相似于Google Test的API编写一个测试工具,然后运用多个后端实行它,而没必要相识底层引擎的庞杂性。它支撑编写单元测试和API序列测试,和自动测试天生。

运用DeepState,我们就可以或许编写一个红黑树(red-black tree)隐约器。今后只需支付较少的勤奋,就可以或许将其酿成一个功用越发周全的测试天生器。 只管DeepState隐约器不需要很多的编码事变,但它支撑回归测试(regressiontest)的重放,以削减用于调试的测试用例的巨细,和多个数据天生后端,包孕Manticore,angr,libFuzzer和AFL。运用符号实行,我们以至发明了原始隐约疏忽的工资引入的破绽。

在此,我包管你浏览完本文后,可以或许完整在自身的API中举行一次高质量的自动化测试。

配景信息

2013年,犹他州大学计算机系的John Regehr撰写了一篇关于“怎样完成ADT的隐约测试”的博客。John细致地议论了一些一样平常性题目,好比代码掩盖率、测试代码和差别测试。若是你还没有浏览John的文章,那末我发起你如今就浏览。

一样平常性的隐约测试很简朴,只需要有一个测试软件,应用John的要领就可以或许在测试工具上供应一组函数或要领。我们在这篇文章中的运转示例是一个红黑树,不外,AVL树、文件体系、内存存储,以至暗码库都可以或许到达相似的测试目的。由于我们的目的是对软件举行完全的测试,而传统的单元测试要领则是编写一系列看起来像以下如许的小函数。

result1 = foo(3, "hello");
result2 = bar(result1, "goodbye")
assert(result2 == DONE);

也就是说,每一个测试都邑按着如许的步调来举行:“先运转一些测试内容,然后搜检它是不是和预期的是一样的。”这类要领有两个题目。起首,事变量很大。其次,这项事变的测试效果其实不像你设想的那样好,每一个测试都只针对一个测试内容,若是测试的人没有提早把潜伏的题目斟酌进去,那末测试历程也就会疏忽这些题目。

而在隐约测试中,用随机坏数据(也称做 fuzz)进击一个顺序,然后等着视察那里遭到了损坏。隐约测试的技能在于,它是不符合逻辑的:自动隐约测试不去预测哪一个数据会致使损坏(就像人工测试员那样),而是将尽可以或很多的芜杂数据投入顺序中。由这个测试考证过的失利形式一般对顺序员来说是个完全的震动,由于任何按逻辑思索的人都不会想到这类失利。隐约测试是一项简朴的手艺,但它却能展现出顺序中的重要破绽。它可以或许考证出实际天下中的错误形式并在您的软件发货前对潜伏的应当被梗塞的进击渠道举行提醒。

隐约测试一般被以为会天生文件或数据包,但它也可以或许天生测试软件库的API挪用序列。

foo_result = NULL;
bar_result = NULL;
repeat LENGTH times:
   switch (choice):
      choose_foo:
         foo_result = foo(randomInt(), randomString());
         break;
      choose_bar:
         bar_result = bar(foo_result, randomString());
         break;
      choose_baz:
         baz_result = baz(foo_result, bar_result);
         break;
   checkInvariants();

也就是说,fuzzer先重复选摘要挪用的随机函数,然后挪用所挑选的函数,测试时期可以或许会存储效果,以便在今后的函数挪用中运用。

John的帖子不只供应一样平常性发起,还包罗了红黑树的事变隐约器的链接。这个隐约器是有效的,它是一个很好的例子,申明了怎样运用基于随机值天生的牢靠测试工具来真正测试API。然则,它也不是一个完整有效的测试工具。它虽然会天生输入,并测试红黑树,但当隐约器发明破绽时,它只会打印一个破绽信息随纵然瓦解。你没有学到任何东西,除“你的代码有一个破绽”如许的信息外,我们再也得不到任何有代价的信息。

抱负状况下,隐约器会自动将失利的测试序列存储在一个文件中,最小化这些序列以简化调试,并且可以或许在回归套件中重放曩昔的失利测试。编写支撑统统这些基础设施的代码异常死板(尤其是在C/ c++中),并且会明显增添测试事变所需的事变量。别的处置惩罚相似捕捉断言违规和硬瓦解的征象,以便在住手之前将测试编写到文件体系,也很难做到。

AFL和其他经常使用的隐约器一般会供应这类功用,这使得隐约测试成为一种更有效的调试工具。不幸的是,这类隐约测试器其实不便于测试API。它们一般会天生一个文件或字节缓冲区,并希冀被测试的顺序将该文件作为输入。将一系列字节转换为红黑树测试可以或许比重新编写更风趣,但事变量也很大。你真正想要的是一个像GoogleTest如许的单元测试框架,但它可以或许转变测试中运用的输入值。有很多很好的随机测试工具,包孕TSTL,但很少有庞杂的工具以C / C ++为目的,并且据我所知,没有一个工具许可你运用除工具内置的随机测试器以外的任何测试天生要领。这就是我们想要的GoogleTest,它可以或许运用libFuzzer,AFL,HonggFuzz或天生数据。

DeepState

DeepState知足了我以上提到的统统测试请求,以至更多。将John的隐约器转换为DeepState测试工具相对轻易,可以或许在文件deepstate_harness.cpp中找到DeepState的重要变动项,统共5项:

1.删除main并用一个已定名的test (test (RBTree, GeneralFuzzer))替代它;

1.1DeepState文件可以或许包罗多个名为test的测试,然则只需一个测试是可以或许用的;

2.只需在每一个测试中建立一个树,而不是运用一个外部轮回来迭代每次影响单个树的挪用:

2.1与隐约测试轮回分歧,我的测试更接近于异常一样平常化的单元测试,即每一个测试都邑实行一个风趣的API挪用序列;

2.2DeepState将处置惩罚运转多个测试,隐约或符号实行引擎将供应“外部轮回”;

3.将每一个API挪用序列的长度流动为流动值,而不是随机值。

3.1文件顶部的#define LENGTH 100掌握我们在每一个测试中挪用的函数数目;

3.2在每次测试中,字节都在雷同的地位,这对基于突变的隐约器很有资助。注重:极长的测试将超越libFuzzer的默许字节长度。

3.3只需它们不斲丧那末多字节使得隐约器或DeepState到达它们的极限,或许找不到要变异的准确字节,更长的测试一般比更短的测试更好。可以或许有一个长度为5的序列暴露了你的破绽,然则DeepState的暴力隐约器以至libFuzzer和AFL可以或许很难找到它,并且更轻易天生雷同题目的长度为45的版本。另一方面,符号实行可以或许找到恣意长度的稀有序列。

3.4为简朴起见,我在我的工具中运用了#define,然则也可以或许将这些测试参数界说为带有默许值的可选敕令行参数,以便在测试中取得更大的灵活性。只需运用与DeepState雷同的工具来界说自身的敕令行选项(请参阅DeepState.c和DeepState.h)。

4用DeepState_Int()、DeepState_Char()和DeepState_IntInRange(…)挪用替代种种rand() % NNN挪用。

4.1 DeepState供应挪用来天生你想要的大多数基础数据类型,可以或许挑选在受限制的范围内天生。

4.2实际上你可以或许运用rand()替代DeepState挪用,若是你的挪用包罗DeepState并已界说DEEPSTATE_TAKEOVER_RAND,则统统rand挪用都将转换为恰当的DeepState函数。 easy_deepstate_fuzzer.cpp文件显现了它的事变道理,但它其实不抱负,由于它不供应任何纪录来显现测试时期发作的状况。这一般是将现有隐约器转换为运用DeepState的最简朴要领。注重:John的隐约器的转变很小,90%的事变只是变动了一些include和删除main。

5. 用DeepState的OneOf构造替代选摘要举行API挪用的switch语句:

————————————-

申博网络安全巴士站

申博-网络安全巴士站是一个专注于网络安全、系统安全、互联网安全、信息安全,全新视界的互联网安全新媒体。

————————————-

5.1 OneOf猎取C ++ lambda的列表,并挑选一个实行;

5.2此变动并非必需的,但运用OneOf可简化代码并许可优化挑选和削减智能测试事变量;

5.3另一个版本的OneOf接收一个流动巨细的数组作为输入,并返回一些值,比方,OneOf(“abcd”)将发生一个字符a,b,c或d。

除此以外,另有很多其他的润饰性(比方格式化,变量定名)变动,但底线就是确保隐约器的本质属性不被损坏。经由过程这些变动,隐约器除不运转fuzz_rb可实行文件,险些和之前一样。我将运用DeepState运转我们界说的测试并天生输入值,选摘要举行的函数挪用,甚么值插进去在红黑树,和由DeepState_Int,OneOf和其他挪用透露表现的统统其他决议计划:

int GetValue() {
  if (!restrictValues) {
    return DeepState_Int();
  } else {
    return DeepState_IntInRange(0, valueRange);
  }
}
...
  for (int n = 0; n < LENGTH; n++) {
    OneOf(
      [&] {
        int key = GetValue();
        int* ip = (int*)malloc(sizeof(int));
        *ip = key;
        if (!noDuplicates || !containerFind(*ip)) {
          void* vp = voidP();
          LOG(TRACE) << n << ": INSERT:" << *ip << " " << vp;
          RBTreeInsert(tree, ip, vp);
          containerInsert(*ip, vp);
        } else {
          LOG(TRACE) << n << ": AVOIDING DUPLICATE INSERT:" << *ip;
          free(ip);
        }
      },
      [&] {
        int key = GetValue();
        LOG(TRACE) << n << ": FIND:" << key;
        if ((node = RBExactQuery(tree, &key))) {
          ASSERT(containerFind(key)) << "Expected to find " << key;
        } else {
          ASSERT(!containerFind(key)) << "Expected not to find " << key;
        }
      },
...

DeepState的装置

DeepState GitHub存储库供应了很多细致信息和依靠项,但在我的MacBook Pro上,装置很简朴。

git clone https://github.com/trailofbits/deepstate
cd deepstate
mkdir build
cd build
cmake ..
sudo make install

构建启用了libFuzzer的版本轻微庞杂一些:

brew install [email protected]
git clone https://github.com/trailofbits/deepstate
cd deepstate
mkdir build
cd build
CC=/usr/local/opt/llvm\@7/bin/clang CXX=/usr/local/opt/llvm\@7/bin/clang++ BUILD_LIBFUZZER=TRUE cmake ..
sudo make install

AFL也可用于为DeepState天生输入,但大多数状况下,原始速率(由于不需要分叉),对照剖析和值配置文件好像为libFuzzer供应了这类API测试的上风。有关在DeepState中运用AFL和其他基于文件的隐约器的更多信息,请参阅DeepState文件。

运用DeepState红黑树隐约器

装置DeepState后,构建红黑树隐约器的历程也就很简朴了。

git clone https://github.com/agroce/rb_tree_demo
cd rb_tree_demo
make

make敕令运用了我们能想到的统统杀毒软件(address、undefined和integer)编译统统内容,以便在隐约处置惩罚中捕捉更多破绽。虽然如许做会下降运转机能,但却很有代价。

若是你运用macOS并运用非Apple clang来取得libFuzzer支撑,那末你需要做以下的事变。

CC=/usr/local/opt/llvm\@7/bin/clang CXX=/usr/local/opt/llvm\@7/bin/clang++ make

如许,你就可以运用到准确的编译器版本,比方,homebrew-installed。

这将为你供应一些分歧的可实行顺序,一个是fuzz_rb,它只是John运用的隐约器,运用时长只需60秒,ds_rb可实行文件是DeepState可实行文件。你可以或许用一个简朴的BF算法隐约器来隐约红黑树。

mkdir tests
./ds_rb --fuzz --timeout 60 --output_test_dir tests

若是要检察有关fuzzer正在实行的操纵的更多信息,可以或许运用–log_level指定日记级别,以明白要检察的信息的重要性。 log_level为0,则代表包孕统统信息,以至包孕调试信息,log_level为1时,代表的是来自被测体系的TRACE信息(比方,由上面显现的LOG(TRACE)代码发生的信息)。log_level为2时,代表的是来自DeepState自身的INFO,非症结信息(这是默许的,一般是适宜的), log_level为3时,代表的是正告信息,依此类推。在隐约测试结束时,测试目次应为空,由于repo中的红黑树代码是没有破绽的。若是将–fuzz_save_passing增加到选项中,你将在目次中获得大批用于通报测试的文件。

末了,我们可以或许运用libFuzzer天生测试。

mkdir corpus
./ds_rb_lf corpus -use_value_profile=1 -detect_leaks=0 -max_total_time=60

ds_rb_lf可实行文件是一般的libFuzzer可实行文件,具有与libFuzzer雷同的敕令行选项。它将运转libFuzzer 60秒,并将任何风趣的输入(包孕测试失利)放在语料库目次中。若是发作瓦解,它将在以后目次中留下瓦解的文件。你可以或许经由过程肯定测试运用的最大输入巨细来调解它,以在某些状况下实行得更好,但这是一项异常重要的演习。在长度为100的状况下,最大巨细和4096字节之间的差异不是异常大。

关于更庞杂的代码,像libFuzzer或AFL如许的基于掩盖的且基于工具的隐约器将比John的隐约器或简朴的DeepState隐约器的随机性更强。关于像红黑树如许的例子,这可以或许没有那末重要。随机性更强的隐约器也具有发生测试语料库的上风,这些测试可以或许发生风趣的代码掩盖。 DeepState许可你运用更快的隐约器举行疾速运转,并运用更智能的工具举行更深切的测试。

我可以或许轻松地重放任何DeepState天生的测试(来自libFuzzer或DeepState的隐约测试器):

./ds_rb --input_test_file file

或许重放全部测试目次:

./ds_rb --input_test_files_dir dir

在重放全部目次时增加–exit_on_fail标记,可让你在碰到失利或瓦解测试时马上住手测试。这类要领可以或许很轻易的用于将DeepState中发明的失利增加到自动回归测试中。

以为的增加一个破绽

虽然统统都很顺遂,但它没有让我对John的隐约或DeepState充满信心。纵然我们变动了Makefile来检察代码掩盖率,也很轻易编写一个不搜检准确行动的隐约器。也就是说隐约测试涵盖了统统内容,除涌现瓦解以外没有发明任何破绽。要检察正在运转的隐约器,和DeepState供应给我们的更多信息,我可以或许主动增加一个破绽。转到red_black_tree.c的第267行,将1改成0。新文件和原始文件的差别应当以下所示:

267c267
<   x->parent->parent->red=0;
---
>   x->parent->parent->red=1;

运用新的red_black_tree.c重修统统隐约器后,运转John的隐约器会马上激发瓦解。

time ./fuzz_rb
Assertion failed: (left_black_cnt == right_black_cnt), function checkRepHelper, file red_black_tree.c, line 702.
Abort trap: 6
 
real 0m0.100s
user 0m0.008s
sys 0m0.070s

运用DeepState隐约器可以或许疾速天生隐约效果:

time ./ds_rb --fuzz --log_level 1 --exit_on_fail --output_test_dir tests
INFO: Starting fuzzing
WARNING: No seed provided; using 1546625762
WARNING: No test specified, defaulting to last test defined (RBTree_GeneralFuzzer)
TRACE: Running: RBTree_GeneralFuzzer from deepstate_harness.cpp(78)
TRACE: deepstate_harness.cpp(122): 0: DELETE:-747598508
TRACE: deepstate_harness.cpp(190): checkRep...
TRACE: deepstate_harness.cpp(192): RBTreeVerify...
TRACE: deepstate_harness.cpp(122): 1: DELETE:831257296
TRACE: deepstate_harness.cpp(190): checkRep...
TRACE: deepstate_harness.cpp(192): RBTreeVerify...
TRACE: deepstate_harness.cpp(134): 2: PRED:1291220586
TRACE: deepstate_harness.cpp(190): checkRep...
TRACE: deepstate_harness.cpp(192): RBTreeVerify...
TRACE: deepstate_harness.cpp(190): checkRep...
TRACE: deepstate_harness.cpp(192): RBTreeVerify...
TRACE: deepstate_harness.cpp(154): 4: SUCC:-1845067087
TRACE: deepstate_harness.cpp(190): checkRep...
TRACE: deepstate_harness.cpp(192): RBTreeVerify...
TRACE: deepstate_harness.cpp(190): checkRep...
TRACE: deepstate_harness.cpp(192): RBTreeVerify...
TRACE: deepstate_harness.cpp(113): 6: FIND:-427918646
TRACE: deepstate_harness.cpp(190): checkRep...
...
TRACE: deepstate_harness.cpp(192): RBTreeVerify...
TRACE: deepstate_harness.cpp(103): 44: INSERT:-1835066397 0x00000000ffffff9c
TRACE: deepstate_harness.cpp(190): checkRep...
TRACE: deepstate_harness.cpp(192): RBTreeVerify...
TRACE: deepstate_harness.cpp(190): checkRep...
TRACE: deepstate_harness.cpp(192): RBTreeVerify...
TRACE: deepstate_harness.cpp(154): 46: SUCC:-244966140
TRACE: deepstate_harness.cpp(190): checkRep...
TRACE: deepstate_harness.cpp(192): RBTreeVerify...
TRACE: deepstate_harness.cpp(190): checkRep...
TRACE: deepstate_harness.cpp(192): RBTreeVerify...
TRACE: deepstate_harness.cpp(103): 48: INSERT:1679127713 0x00000000ffffffa4
TRACE: deepstate_harness.cpp(190): checkRep...
Assertion failed: (left_black_cnt == right_black_cnt), function checkRepHelper, file red_black_tree.c, line 702.
ERROR: Crashed: RBTree_GeneralFuzzer
INFO: Saved test case to file `tests/6de8b2ffd42af6878875833c0cbfa9ea09617285.crash`
...
real 0m0.148s
user 0m0.011s
sys 0m0.131s

为了轻易本文的论述,我做了一些精简,上面的代码只是细致输出的一局部。DeepState保与John的隐约器的最大区分在于,它生存了一个测试用例。固然,生存的测试用例的称号会有所分歧,由于每一个已生存的测试都邑天生独一称号。重放测试以下所示:

./ds_rb --input_test_file tests/6de8b2ffd42af6878875833c0cbfa9ea09617285.crash

并且我会再次看到全部历程细节,如上所述,这一长串看似恣意的操纵并非最有资助的测试。此时,DeepState可以或许资助我们找到有效的信息。

deepstate-reduce ./ds_rb tests/6de8b2ffd42af6878875833c0cbfa9ea09617285.crash minimized.crash
ORIGINAL TEST HAS 8192 BYTES
LAST BYTE READ IS 509
SHRINKING TO IGNORE UNREAD BYTES
ONEOF REMOVAL REDUCED TEST TO 502 BYTES
ONEOF REMOVAL REDUCED TEST TO 494 BYTES
...
ONEOF REMOVAL REDUCED TEST TO 18 BYTES
ONEOF REMOVAL REDUCED TEST TO 2 BYTES
BYTE RANGE REMOVAL REDUCED TEST TO 1 BYTES
BYTE REDUCTION: BYTE 0 FROM 168 TO 0
NO (MORE) REDUCTIONS FOUND
PADDING TEST WITH 49 ZEROS
 
WRITING REDUCED TEST WITH 50 BYTES TO minimized.crash

一样,我省略了削减测试的一些冗杂历程,新的测试效果更轻易明白。

./ds_rb --input_test_file minimized.crash
WARNING: No test specified, defaulting to last test defined (RBTree_GeneralFuzzer)
TRACE: Initialized test input buffer with data from `minimized.crash`
TRACE: Running: RBTree_GeneralFuzzer from deepstate_harness.cpp(78)
TRACE: deepstate_harness.cpp(103): 0: INSERT:0 0x0000000000000000
TRACE: deepstate_harness.cpp(190): checkRep...
TRACE: deepstate_harness.cpp(192): RBTreeVerify...
TRACE: deepstate_harness.cpp(103): 1: INSERT:0 0x0000000000000000
TRACE: deepstate_harness.cpp(190): checkRep...
TRACE: deepstate_harness.cpp(192): RBTreeVerify...
TRACE: deepstate_harness.cpp(103): 2: INSERT:0 0x0000000000000000
TRACE: deepstate_harness.cpp(190): checkRep...
Assertion failed: (left_black_cnt == right_black_cnt), function checkRepHelper, file red_black_tree.c, line 702.
ERROR: Crashed: RBTree_GeneralFuzzer

我们只需要在树中插进去三个雷同的值就可以或许发明个中存在的破绽,在继承操纵之前,请记得修复red_black_tree.c!

你可以或许点此链接,寓目全部历程。

在第2局部中,我将对测试的效果举行评价,看看DeepState测试是不是与John的隐约测试一样有效?看看这两种要领在查找某些潜伏的破绽方面是不是一样有效?符号实行是不是也有一样的效果呢?敬请存眷。

华硕内网暗码在GitHub上泄漏

北京时间3月28日早间消息,据美国科技媒体TechCrunch报道,一名信息安全研究员两个月前向华硕发出警告称,有华硕员工在GitHub代码库中错误地发布了密码。这些密码可以被用于访问该公司的企业内网。 其中一个密码出现在一名员工分享的代码


申博|网络安全巴士站声明:该文看法仅代表作者自己,与本平台无关。版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明运用DeepState对API举行隐约测试
喜欢 (0)
[]
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址