软牛科技逆向开发工程师一面

本来投递的是软牛科技的Cpp开发岗,然后HR表示Cpp已经招满,只剩逆向方向,然后我就转了逆向方向,之前也没有逆向相关的经验,只是懂点RISC-V汇编、反汇编过一些ELF可执行文件,但抱着试试看的想法,还是参加了笔试,笔试主要都是C/C++的基本知识点考察,只有一道跟逆向相关的直接空过了,后面交了笔试之后有一段时间没咨询HR,结果一直没有反馈,后面想起了这茬,问了一下HR才说笔试通过了,可以安排面试。

  1. 自我介绍。
  2. 对逆向岗位的了解有多少?
  3. 看没看过《汇编语言》(王爽)?(回答看了一点,后面因为没有需求就没看了,主要看RISC-V指令集。)
  4. 汇编语言中,函数是如何传参的?(这里他想问的可能是x86,但是我不太了解,于是我就答了RISC-V函数调用的时候参数是放到a0-a7寄存器里,超过的参数会放在栈上传递。)
  5. 之前有没有调试过汇编?(答了在用gdb调试项目里的内核代码的时候,有时候会用gdb看看汇编指令,顺便也讲了RISC-V函数调用的过程,先压栈ra寄存器,然后压栈fp、sp寄存器,然后申请栈上变量,返回时恢复ra、sp、fp。)
  6. 知道函数调用中的传参顺序吗?(答了第一个参数放到a0,以此类推直到a7,更多的参数放在栈上。)
  7. 可能我没描述清楚,假设我有一个函数f(int a, int b, int c, int d),这四个参数在汇编的时候它们传到函数内部的顺序是什么样的,先传哪一个?(这个问题没听明白,不太清楚想问的是什么,于是就答了C++标准对于参数的求值顺序应该是没有指定的,由实现来决定参数的求值顺序,至于传入顺序,感觉就是从左到右传递,也即从第一个参数开始传递。)
  8. 你对C++的函数调用约定了解过么?(答了没了解过。这个之前没有了解过,当时没答上来,后面搜了一下才知道原来就是之前看好多函数声明前面带着的符号__cdecl之类的一类符号就叫C++函数调用约定,涨了一波知识。
  9. 你说你是通过自学的方式学习C++的,你看过C++的哪本书?(答了《C++程序设计语言》(1-3部分)。)
  10. 说说C和C++有哪些区别?(答了C++引入了一些抽象机制,比如类的继承多态,模板,移动语义,lambda表达式,仿函数等。)
  11. 说说在笔试题里如何区别重载函数的关键字你为什么要选择virtual?(答了因为如果父类有virtual函数,派生类可以通过重载这个虚函数,来实现多态机制,也即在通过父类引用或指针来调用这个虚函数的时候,会根据实际引用或指向的实参不同而分别调用不同的实现,这样感觉能实现函数重载。后面复盘的时候才发现好像把函数重载和子类重写父类函数两个概念给搞混了,脑子抽了。
  12. 假设父类里面有个函数f参数是int,派生类中有个同名函数参数是const int,那子类中这个函数会覆盖掉父类中的函数么?(答了不会,因为它们的参数类型不同。当时真是没反应过来,后来才回过神来,对于一个实际的int参数,编译器根本没办法区分是调用const int还是int,所以子类的实现应该可以覆盖掉父类的实现的。
  13. 有了解过C++重载是怎么实现的么?(答了C++编译器会把参数的类型也编码到函数的名字里,这样即使函数名字相同,但它们的参数列表不同,编译器也会认为它们是不同的两个函数。)
  14. 假设在全局定义了一个函数f参数是int,另一个函数f参数是const int,那么这两个函数实现重载了么?(答了可以实现重载,因为它们的参数类型不同。面试官继续问这个问题,应该就是确认一下之前那里我确实答错了,实际上应该是不算重载的,因为没法区分。
  15. 讲讲构造函数和析构函数的调用顺序?(答了构造函数先调用每个成员的构造函数然后执行自己的构造函数,最后构造函数返回,成功构造,析构的话先调用自己的析构函数,然后调用成员的析构函数,所有析构结束之后返回,成功析构。这里忘说了继承情况下构造时应该首先执行父类的构造函数,析构时最后还需执行父类的析构函数。
  16. 假设一个类里有多个成员,那么这多个成员的构造函数调用顺序是怎么样的?(答了按照成员在类声明中的声明顺序来调用的。)
  17. 假设一个类没有数据成员,那么这个类在内存中占大小多大?(答了如果有虚函数的话会占一个指针大小的空间,如果没有的话所占空间是0Byte。后面查了一下发现所占空间不是0B,是1B,是因为C++标准规定完整对象的大小不能是0,为了区分不同的对象,所以最小只能是1,但是在继承中,空类可以不占空间。
  18. 你刚才说如果有虚函数,那所占空间是个指针大小,那么具体是多大呢?(答了地址空间是32位的话就是4B,64位的话就是8B。)
  19. 假设我有一个结构体第一个成员是int,第二个成员是long,这个结构体在32位机器和64位机器上所占空间是一样大的吗?(答了标准规定long大小是大于等于int,在64位机上long和int应该是一样大的,都是4B,在32位机上long应该是比int大的,但是考虑到内存对齐的话,可能两个结构体是一样大的。这个地方后来查了一下也答错了,64位机上long比int大,long是8B,int是4B,32位机上long和int一样大都是4B。
  20. 如果想要这两结构体在32位和64位机上大小一致,可以使用什么策略?(答了可以用内存对齐来实现。)
  21. 之前是否使用过VisualStudio这个开发工具?(答了,之前使用过,现在使用CLion。)
  22. 对内存的话有什么了解呢?(这个问的有点宽泛,就问了具体想问什么,面试官也没继续纠结,转而开启下一个问题。)
  23. 看你玩过操作系统,那你对PE文件有了解么?(答了没有了解,但是猜到可能是Windows上的可执行文件的格式,于是就简单讲了讲Linux系统的ELF可执行文件格式,也不太懂,就大概模糊的讲了一下。)
  24. 讲讲堆和栈的区别?(堆上分配的对象需要手动释放,栈上分配的对象会自动释放,堆上一般分配大的对象通过指针访问,栈上一般不分配大的对象,栈是从高地址向低地址增长。)
  25. 了解什么是栈溢出和堆溢出吗?(答了操作系统会通过在栈的上下设置不能访问的页面作为哨兵来检测栈溢出,当访问的地址到了这两个哨兵页面就会产生缺页中断,操作系统就会发现产生栈溢出,从而执行对应的处理策略,而堆溢出的话有可能是在堆上分配的对象过多或者对象过大,或者是产生了内存泄漏,从而使得堆空间被用尽,导致发生堆溢出。)
  26. 平时会使用什么方法来避免这些情况?(这个的话因为平时也没怎么遇到过,所以就岔开话题,答了xv6是如何检测栈溢出和堆溢出的,栈溢出是通过哨兵页面,堆溢出的话之前没处理过。)
  27. 假如在Windows上编写多线程程序,开多少个线程是比较好的?(这个直接给我问住了,一下不知道咋答了,后来就答了一个Amdahl定律和CPU核心数限制同时并行执行的线程数,还提了一嘴因特尔的超线程。)
  28. 之前有了解过死锁吗?(答了死锁产生的四个条件,然后避免死锁可以破坏其中任意一个条件,举了GPU调度线程执行时提前分配好了线程需要的所有资源,从而破坏占有且等待条件从而可以避免死锁,还有使用银行家算法在进程申请资源时检测在分配资源后系统是否会进入危险状态,如果会进入危险状态则不分配资源,从而避免死锁。)
  29. 看你之前学习过一些汇编语言,你对汇编语言怎么看待?
  30. 反问环节。

一面面试官说是感觉答得还可以,所以去叫部门主管来继续面一次,应该也算是二面了。

  1. 对逆向方向是否有兴趣?
  2. 可以去看一下《加密与解密》前八章,如果感兴趣后面可以再聊。
  3. 看到你参加了ACM这个竞赛你主要负责哪些方面的算法?(动态规划和图论相关的算法都学习过,还学过一些基础的计算几何。)
  4. 之前读过或者手写过汇编级别的程序么?(答了在做项目的时候,在上下文切换的时候需要手写汇编代码,然后用户进程陷入内核的话需要读汇编代码。)
  5. 讲一讲线程上下文切换的时候做了什么?(答了操作系统在内核中进行内核线程的切换的时候,首先保存当前内核线程的callee保存的寄存器,然后保存返回地址ra以及栈顶指针sp,之后将之前暂停的另一个线程的保存的寄存器加载到CPU中,从而实现线程的上下文切换,而用户进程陷入内核的时候,不能只保存callee保存的寄存器,还需要保存所有可用的寄存器,以及指向页表的寄存器,指向用户栈的寄存器,pc寄存器等寄存器,才能完成陷入内核的操作,在从内核退出前再次恢复之前保存的寄存器,从而实现了,用户进程陷入内核和恢复执行。)
  6. 讲一讲进程陷入内核态的时候用到了哪些汇编指令?(答了ld,sd,jalr,ecall。)
  7. 看你这个项目是个操作系统内核,你平时怎么调试这个内核?(答了使用gdb server调试。)
  8. 你平时都会使用什么调试方法?(答了会打断点,然后查看backtrace,然后使用printf语句。)
  9. 假如你的程序中有内存越界问题或者内存泄漏,有没有什么方法来排查?(这两个问题都不太会,之前没了解过,所以就大概乱答了一下。)
  10. 汇编语言如何实现条件分支?(答了RISC-V提供了beq之类的分支语句,通过判断两个寄存器的值是否相等来决定是否跳转到指定地址执行,从而实现分支以及循环。)
  11. 循环一般有三种写法,你觉得哪种效率最高?(答了我觉得while(expr){}这种写法效率最高。)
  12. 函数调用中,栈是如何变化的?(答了先把ra、fp、sp寄存器入栈,然后再保存一些在函数中用到的callee保存寄存器,然后改变栈指针分配栈上的变量,返回前再将之前保存的寄存器恢复即可。)
  13. 反问环节。

总结:挺多问题没太答好,而且可能项目技能和岗位相关性不太高,这家公司开发主要是在Windows上做逆向开发,Linux上的一些知识就不太有用,所以后面挂了也是可以理解的。

全部评论
都过了,到了HR面,然后不想面了= =感觉薪资有点低
4 回复 分享
发布于 2023-09-22 18:43 江苏
这感觉不容易啊,之前还想考虑去试试,现在感觉还是算了
1 回复 分享
发布于 2023-07-11 16:49 广东
二面有给博主时间看吗
点赞 回复 分享
发布于 2023-06-18 18:47 福建
一面已经可以挂了,对逆向一点不熟,面试官很留面子了
点赞 回复 分享
发布于 2023-06-21 00:51 山西
答得还可以了叭,这都挂了😭
点赞 回复 分享
发布于 2023-07-18 10:09 江西
我是二面挂了😭
点赞 回复 分享
发布于 2023-08-15 23:27 安徽

相关推荐

不愿透露姓名的神秘牛友
11-22 16:35
点赞 评论 收藏
分享
12 38 评论
分享
牛客网
牛客企业服务