我正在阅读我的C++讲师的一些讲义,他写了以下内容:
- 使用缩进//确定
- 永远不要依赖运算符优先级 - 始终使用括号//确定
- 总是使用{}块 - 即使是单行// 不行,为什么???
- 比较左侧的Const对象// OK
- 对于> = 0 //好玩法的变量使用无符号
- 删除后将指针设置为NULL - 双删除保护//不错
第三种技术对我来说并不清楚:通过在一条线中放置一条线可以获得{ ... }什么?
例如,拿这个奇怪的代码:
int j = 0;
for (int i = 0 ; i < 100 ; ++i)
{
if (i % 2 == 0)
{
j++;
}
}
Run Code Online (Sandbox Code Playgroud)
并替换为:
int j = 0;
for (int i = 0 ; i < 100 ; ++i)
if (i % 2 == 0)
j++;
Run Code Online (Sandbox Code Playgroud)
使用第一个版本有什么好处?
我已经是一名专业软件工程师,已经有一年的时间了,已经获得了CS学位.我已经知道C++和C中有一段时间的断言,但直到最近才知道它们在C#和.NET中存在.
我们的生产代码不包含任何断言,我的问题是......
我应该在生产代码中开始使用Asserts吗?如果是这样,它的使用何时最合适?这样做会更有意义吗?
Debug.Assert(val != null);
Run Code Online (Sandbox Code Playgroud)
要么
if ( val == null )
throw new exception();
Run Code Online (Sandbox Code Playgroud) language-agnostic testing defensive-programming exception assertions
我需要在我的C++应用程序中存储敏感信息(我想保密的对称加密密钥).简单的方法是这样做:
std::string myKey = "mysupersupersecretpasswordthatyouwillneverguess";
但是,通过该strings过程(或从二进制应用程序中提取字符串的任何其他应用程序)运行应用程序将显示上述字符串.
应使用哪些技术来掩盖这些敏感数据?
编辑:
好的,所以你们所有人都说"你的可执行文件可以进行逆向工程" - 当然!这是我的一个宠儿,所以我要在这里咆哮:
为什么99%(好吧,或许我夸大一点)这个网站上所有与安全相关的问题都会被"没有可能的方法来创建一个完全安全的程序"所回答 - 这不是一个有用的回答!安全性是完美可用性与一端无安全性之间的滑动尺度,完美的安全性,但另一方面没有可用性.
关键在于,您可以根据您要执行的操作以及运行软件的环境来选择滑动比例.我不是在为军事装置编写应用程序,我正在为家用PC编写应用程序.我需要使用预先知道的加密密钥在不受信任的网络上加密数据.在这些情况下,"通过默默无闻的安全"可能已经足够了!当然,有足够时间,精力和技能的人可以对二进制文件进行逆向工程并找到密码,但猜猜是什么?我不在乎:
实施顶级安全系统所花费的时间比破解版本的销售损失更为昂贵(不是说我实际上是卖这个,但你明白了我的意思).在新程序员的编程中,这个蓝天"让我们尽可能做到绝对最好的方式"的趋势至少可以说是愚蠢的.
感谢您抽出宝贵时间回答这个问题 - 他们最有帮助.不幸的是,我只能接受一个答案,但我已经投了所有有用的答案.
Erlang(或者Joe Armstrong的?)建议不要使用防御性编程并让进程崩溃(而不是用不必要的守卫试图跟踪残骸污染你的代码)对我来说非常有意义,因为我想知道为什么我浪费了这么多多年来一直在努力解决错误!
我想知道的是 - 这种方法只适用于像Erlang这样的平台吗?Erlang有一个VM,它具有对进程监督树的简单本机支持,并且重启进程非常快.我是否应该花费我的开发工作(当不在Erlang世界时)重新创建监督树而不是用顶级异常处理程序,错误代码,空结果等等来掩盖自己.
您是否认为这种方法的改变在(或者说).NET或Java空间中运行良好?
对于32位系统(无论是Linux,Mac OS或Windows,PowerPC还是x86)的C++开发,我已经初始化了指针,否则这些指针将被定义(例如,它们无法立即获得正确的值),如下所示:
int *pInt = reinterpret_cast<int *>(0xDEADBEEF);
Run Code Online (Sandbox Code Playgroud)
(为了节省打字和DRY,右侧通常是常数,例如BAD_PTR.)
如果在获得正确值之前取消引用pInt,那么它将在大多数系统上立即崩溃(而不是在某些内存被覆盖或进入非常长的循环时崩溃).
当然,行为取决于底层硬件(从用户进程获取奇数地址0xDEADBEEF的4字节整数可能完全有效),但崩溃对于我迄今为止开发的所有系统都是100%可靠的( Mac OS 68xxx,Mac OS PowerPC,Linux Redhat Pentium,Windows GUI Pentium,Windows控制台Pentium).例如,在PowerPC上,从奇数地址获取4字节整数是非法的(总线故障).
在64位系统上,这有什么好处呢?
我正在使用一个用于创建数据库连接的小例程:
public DbConnection GetConnection(String connectionName)
{
ConnectionStringSettings cs= ConfigurationManager.ConnectionStrings[connectionName];
DbProviderFactory factory = DbProviderFactories.GetFactory(cs.ProviderName);
DbConnection conn = factory.CreateConnection();
conn.ConnectionString = cs.ConnectionString;
conn.Open();
return conn;
}
Run Code Online (Sandbox Code Playgroud)
然后我开始研究.NET框架文档,看看各种事物的记录行为是什么,看看我是否可以处理它们.
例如:
ConfigurationManager.ConnectionStrings...
Run Code Online (Sandbox Code Playgroud)
该文件说,打电话的ConnectionStrings抛出一个ConfigurationErrorException如果无法检索集合.在这种情况下,我无法处理此异常,所以我会放手.
下一部分是ConnectionStrings的实际索引,以查找connectionName:
...ConnectionStrings[connectionName];
Run Code Online (Sandbox Code Playgroud)
在这种情况下,ConnectionStrings文档说如果找不到连接名,该属性将返回null.我可以检查是否发生了这种情况,并抛出一个例外,让某人高兴他们给了一个无效的connectionName:
ConnectionStringSettings cs=
ConfigurationManager.ConnectionStrings[connectionName];
if (cs == null)
throw new ArgumentException("Could not find connection string \""+connectionName+"\"");
Run Code Online (Sandbox Code Playgroud)
我重复同样的练习:
DbProviderFactory factory =
DbProviderFactories.GetFactory(cs.ProviderName);
Run Code Online (Sandbox Code Playgroud)
该GetFactory方法对如果指定一家工厂发生了什么没有文档ProviderName找不到.它没有记录返回null,但我仍然可以防御,并检查 null:
DbProviderFactory factory = …Run Code Online (Sandbox Code Playgroud) 是否可以split返回null String[]?我很好奇,因为我想在我的代码中尽可能地保持防御,而不需要进行不必要的检查.代码如下:
String[] parts = myString.split("\\w");
Run Code Online (Sandbox Code Playgroud)
在使用parts后分割之前,是否需要执行空检查?
阅读以下博客后:
http://xania.org/200711/ambiguous-overloading
我开始问自己"我不应该总是明确地定义我的构造函数吗?"
所以我开始阅读的不仅仅是发现这篇文章:
http://www.sjbrown.co.uk/2004/05/01/always-use-explicit/
这显示了另一个例子,也解释了他背后的想法.但当然这是博客的一个想法.
我很高兴听到你们中的一些人,你对这种态度的看法,你对这个主题的经验是什么,以及对于任何一种方式的一些例子都会很好.
我发现可以从二进制文件中提取硬编码字符串.
例如,Process Explorer的属性视图显示超过3个字符的所有字符串.
这是我编写的简单可执行文件的代码,只是为了测试它:
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
_TCHAR* hiddenString1 =_T("4537774B-CC80-4eda-B3E4-7A9EE77991F5");
_TCHAR* hiddenString2 =_T("hidden_password_or_whatever");
for (int i= 0; i<argc; i++) {
if (0 == _tcscmp(argv[i],hiddenString1)) {
_tprintf (_T("The guid argument is correct.\n")); }
else if (0 == _tcscmp(argv[i],hiddenString2)) {
_tprintf (_T("Do something here.\n")); }
}
_tprintf (_T("This is a visible string.\n"));
//Keep Running
Sleep(60000);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
字符串可以清楚地从相应的可执行文件中提取:

我认为找到字符串有点太容易了.
我的问题是:
c++ security obfuscation defensive-programming reverse-engineering
我在过去的3年里一直在编程.当我编程时,我用来处理所有已知的异常并优雅地提醒用户.我最近看到了一些代码,几乎所有方法都包含在try/catch块中.作者说它是防御性编程的一部分.我想知道,这真的是防御性编程吗?您是否建议将所有代码放入try块中?
c++ ×5
java ×2
obfuscation ×2
security ×2
.net ×1
64-bit ×1
assertions ×1
c ×1
c# ×1
coding-style ×1
constructor ×1
curly-braces ×1
debugging ×1
erlang ×1
exception ×1
explicit ×1
string ×1
testing ×1